diff --git a/examples/Shim/BasicShim/BasicShim.anf b/examples/Shim/BasicShim/BasicShim.anf new file mode 100644 index 00000000..c1005841 --- /dev/null +++ b/examples/Shim/BasicShim/BasicShim.anf @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/examples/Shim/BasicShim/BasicShim.ned b/examples/Shim/BasicShim/BasicShim.ned new file mode 100644 index 00000000..d3984af5 --- /dev/null +++ b/examples/Shim/BasicShim/BasicShim.ned @@ -0,0 +1,46 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.examples.Shim.BasicShim; + +import ned.DatarateChannel; +import rina.src.CS.EthShim.Host1APShim; + + +network BasicShim +{ + types: + channel ethline extends DatarateChannel + { + delay = 50ns; + datarate = 100Mbps; + } + submodules: + host1: Host1APShim { + @display("p=82,92"); + } + host2: Host1APShim { + @display("p=231,92"); + } + connections allowunconnected: + host1.medium <--> ethline <--> host2.medium; +} diff --git a/examples/Shim/BasicShim/config.xml b/examples/Shim/BasicShim/config.xml new file mode 100644 index 00000000..92a8d0d8 --- /dev/null +++ b/examples/Shim/BasicShim/config.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12000000 + 1000 + 24000000 + 2000 + 10000000 + 1000000 + 0.01 + 0 + 1489 + 1 + 1 + 0 + 0 + 1000000 + 500000 + 0 + 0 + 0 + 0 + 0 + 0 + + + diff --git a/examples/Shim/BasicShim/omnetpp.ini b/examples/Shim/BasicShim/omnetpp.ini new file mode 100644 index 00000000..c53f8d7f --- /dev/null +++ b/examples/Shim/BasicShim/omnetpp.ini @@ -0,0 +1,68 @@ +[General] +network = BasicShim +debug-on-errors = true +repeat = 5 +seed-set = ${runnumber} +sim-time-limit = 5min + +**.host1.applicationProcess1.apName = "App1" +**.host2.applicationProcess1.apName = "App2" +**.apType = "APPing" + +#Static addressing +**.host1.ipcProcessShim.ipcAddress = "1" +**.host2.ipcProcessShim.ipcAddress = "2" + +**.host1.ipcProcess1.ipcAddress = "11" +**.host2.ipcProcess1.ipcAddress = "22" + +**.ipcProcessShim.difName = "50" +**.ipcProcess1.difName = "Layer1" + +#DIF Allocator settings +**.host1.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='host1']/DA") +**.host2.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='host2']/DA") + +#QoS settings +**.ra.qoscubesData = xmldoc("config.xml", "Configuration/QoSCubesSet") + +**.host2.**.enrollment.isSelfEnrolled = true + +[Config PingFC] +fingerprint = "24c6-353c" +#PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.stopAt = 200s +**.defaultMaxQLength = 150 +**.defaultThreshQLength = 100 +**.host*.ipcProcess1.efcp.efcp.rtt = 8s + +[Config PingRX] +fingerprint = "24c6-353c" +#PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.rate = 100 +**.host1.applicationProcess1.apInst.stopAt = 200s +**.host1.ipcProcess1.efcp.efcp.pduDroppingEnabled = true + +[Config Ping] +fingerprint = "24c6-353c" +#PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.rate = 10 +**.host1.applicationProcess1.apInst.stopAt = 200s +**.host1.ipcProcess1.efcp.efcp.ecnPolicy = "DTCPECNPolicyDefault" + +[Config Ping-AppQos] +fingerprint = "24c6-353c" +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.rate = 10 +**.host1.applicationProcess1.apInst.stopAt = 200s +**.applicationEntity.AEMonitor.**.iae.averageBandwidth = 1000000bps +**.applicationEntity.AEMonitor.**.iae.maxAllowGap = 10 +**.applicationEntity.AEMonitor.**.iae.delay = 10000 us +**.applicationEntity.AEMonitor.**.iae.undetectedBitErr = 0.01 diff --git a/examples/Shim/SimpleNetworkShim/SimpleNetworkShim.anf b/examples/Shim/SimpleNetworkShim/SimpleNetworkShim.anf new file mode 100644 index 00000000..1554e538 --- /dev/null +++ b/examples/Shim/SimpleNetworkShim/SimpleNetworkShim.anf @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/examples/Shim/SimpleNetworkShim/SimpleNetworkShim.ned b/examples/Shim/SimpleNetworkShim/SimpleNetworkShim.ned new file mode 100644 index 00000000..30ab684e --- /dev/null +++ b/examples/Shim/SimpleNetworkShim/SimpleNetworkShim.ned @@ -0,0 +1,72 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.examples.Shim.SimpleNetworkShim; + +import rina.src.CS.EthShim.Host1APShim; +import rina.src.CS.EthShim.InteriorRouter2IntShim; + +import inet.node.ethernet.Eth100M; +import inet.node.ethernet.EtherSwitch; + + +network SimpleNetworkShim +{ + @display("bgb=492,282"); + submodules: + host11: Host1APShim { + @display("p=64,62"); + } + host12: Host1APShim { + @display("p=64,123"); + } + host13: Host1APShim { + @display("p=64,187"); + } + switch1: EtherSwitch { + @display("p=151,122"); + } + interiorRouter: InteriorRouter2IntShim { + @display("p=250,123"); + } + switch2: EtherSwitch { + @display("p=349,122"); + } + host21: Host1APShim { + @display("p=441,62"); + } + host22: Host1APShim { + @display("p=441,123"); + } + host23: Host1APShim { + @display("p=441,187"); + } + connections allowunconnected: + host11.medium <--> Eth100M <--> switch1.ethg++; + host12.medium <--> Eth100M <--> switch1.ethg++; + host13.medium <--> Eth100M <--> switch1.ethg++; + interiorRouter.medium++ <--> Eth100M <--> switch1.ethg++; + interiorRouter.medium++ <--> Eth100M <--> switch2.ethg++; + host21.medium <--> Eth100M <--> switch2.ethg++; + host22.medium <--> Eth100M <--> switch2.ethg++; + host23.medium <--> Eth100M <--> switch2.ethg++; +} diff --git a/examples/Shim/SimpleNetworkShim/config.xml b/examples/Shim/SimpleNetworkShim/config.xml new file mode 100644 index 00000000..a00e659e --- /dev/null +++ b/examples/Shim/SimpleNetworkShim/config.xml @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12000000 + 1000 + 24000000 + 2000 + 10000000 + 1000000 + 0.01 + 0 + 1500 + 1 + 1 + 0 + 0 + 1000000 + 500000 + 0 + 0 + 0 + 0 + 0 + 0 + + + diff --git a/examples/Shim/SimpleNetworkShim/omnetpp.ini b/examples/Shim/SimpleNetworkShim/omnetpp.ini new file mode 100644 index 00000000..87f501b5 --- /dev/null +++ b/examples/Shim/SimpleNetworkShim/omnetpp.ini @@ -0,0 +1,93 @@ +[General] +network = SimpleNetworkShim +check-signals = true +repeat = 5 +sim-time-limit = 5min +debug-on-errors = true +seed-set = ${runnumber} + +# Set IEEE802.1q encapsulation for VLANs in the switches (already set in shim IPC Processes) +*.switch*.eth[*].qEncap.typename = "Ieee8021qEncap" + +*.switch1.eth[*].qEncap.inboundVlanIdFilter = "50" +*.switch1.eth[*].qEncap.outboundVlanIdFilter = "50" +*.switch2.eth[*].qEncap.inboundVlanIdFilter = "60" +*.switch2.eth[*].qEncap.outboundVlanIdFilter = "60" + +*.host11.applicationProcess1.apName = "App11" +*.host12.applicationProcess1.apName = "App12" +*.host13.applicationProcess1.apName = "App13" +*.host21.applicationProcess1.apName = "App21" +*.host22.applicationProcess1.apName = "App22" +*.host23.applicationProcess1.apName = "App23" +**.apType = "APPing" + +*.host11.ipcProcessShim.ipcAddress = "1" +*.host12.ipcProcessShim.ipcAddress = "2" +*.host13.ipcProcessShim.ipcAddress = "3" +*.interiorRouter.ipcProcessShim0.ipcAddress = "4" +*.host21.ipcProcessShim.ipcAddress = "1" +*.host22.ipcProcessShim.ipcAddress = "2" +*.host23.ipcProcessShim.ipcAddress = "3" +*.interiorRouter.ipcProcessShim1.ipcAddress = "4" + +*.host11.ipcProcess1.ipcAddress = "11" +*.host12.ipcProcess1.ipcAddress = "12" +*.host13.ipcProcess1.ipcAddress = "13" +*.host21.ipcProcess1.ipcAddress = "21" +*.host22.ipcProcess1.ipcAddress = "22" +*.host23.ipcProcess1.ipcAddress = "23" +*.interiorRouter.relayIpc.ipcAddress = "33" + +*.host1*.ipcProcessShim.difName = "50" +*.interiorRouter.ipcProcessShim0.difName = "50" + +*.host2*.ipcProcessShim.difName = "60" +*.interiorRouter.ipcProcessShim1.difName = "60" + +*.host*.ipcProcess1.difName = "Layer11" +*.interiorRouter.relayIpc.difName = "Layer11" + +#DIF Allocator settings +*.host1*.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='hosts1']/DA") +*.host2*.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='hosts2']/DA") +*.interiorRouter.difAllocator.configData = xmldoc("config.xml", "Configuration/Router[@id='interiorRouter']/DA") + +#QoS Cube sets +**.ra.qoscubesData = xmldoc("config.xml", "Configuration/QoSCubesSet") + +#Specify timeout of CreateRequest message +#**.fa.createRequestTimeout = 15s + +**.printAtEnd = true + +[Config Ping] +fingerprint = "529f-aef6" + +#PingApp setup +*.host11.applicationProcess1.apInst.dstApName = "App23" +*.host11.applicationProcess1.apInst.startAt = 10s +*.host11.applicationProcess1.apInst.stopAt = 200s + +[Config PingAll] +fingerprint = "529f-aef6" + +#PingApp setup +*.host11.applicationProcess1.apInst.dstApName = "App21" +*.host11.applicationProcess1.apInst.startAt = 10000ms +*.host11.applicationProcess1.apInst.stopAt = 200s +*.host12.applicationProcess1.apInst.dstApName = "App22" +*.host12.applicationProcess1.apInst.startAt = 10100ms +*.host12.applicationProcess1.apInst.stopAt = 200s +*.host13.applicationProcess1.apInst.dstApName = "App23" +*.host13.applicationProcess1.apInst.startAt = 10200ms +*.host13.applicationProcess1.apInst.stopAt = 200s +*.host21.applicationProcess1.apInst.dstApName = "App11" +*.host21.applicationProcess1.apInst.startAt = 10050ms +*.host21.applicationProcess1.apInst.stopAt = 200s +*.host22.applicationProcess1.apInst.dstApName = "App12" +*.host22.applicationProcess1.apInst.startAt = 10150ms +*.host22.applicationProcess1.apInst.stopAt = 200s +*.host23.applicationProcess1.apInst.dstApName = "App13" +*.host23.applicationProcess1.apInst.startAt = 10250ms +*.host23.applicationProcess1.apInst.stopAt = 200s diff --git a/examples/Shim/SimpleRelayShim/SimpleRelayShim.anf b/examples/Shim/SimpleRelayShim/SimpleRelayShim.anf new file mode 100644 index 00000000..90aeb4c3 --- /dev/null +++ b/examples/Shim/SimpleRelayShim/SimpleRelayShim.anf @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/examples/Shim/SimpleRelayShim/SimpleRelayShim.ned b/examples/Shim/SimpleRelayShim/SimpleRelayShim.ned new file mode 100644 index 00000000..4c3ad5b5 --- /dev/null +++ b/examples/Shim/SimpleRelayShim/SimpleRelayShim.ned @@ -0,0 +1,46 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.examples.Shim.SimpleRelayShim; + +import ned.DatarateChannel; +import rina.src.CS.EthShim.Host1APShim; +import rina.src.CS.EthShim.InteriorRouter2IntShim; + + +network SimpleRelayShim +{ + @display("bgb=368,202"); + submodules: + host1: Host1APShim { + @display("p=70,101"); + } + interiorRouter: InteriorRouter2IntShim { + @display("p=180,101"); + } + host2: Host1APShim { + @display("p=290,101"); + } + connections allowunconnected: + host1.medium <--> DatarateChannel {datarate = 100Mbps; delay = 100us; ber = 0; } <--> interiorRouter.medium++; + host2.medium <--> DatarateChannel {datarate = 100Mbps; delay = 100us; ber = 0; } <--> interiorRouter.medium++; +} diff --git a/examples/Shim/SimpleRelayShim/config.xml b/examples/Shim/SimpleRelayShim/config.xml new file mode 100644 index 00000000..68c9851a --- /dev/null +++ b/examples/Shim/SimpleRelayShim/config.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12000000 + 1000 + 24000000 + 2000 + 10000000 + 1000000 + 0.01 + 0 + 1500 + 1 + 1 + 0 + 0 + 1000000 + 500000 + 0 + 0 + 0 + 1 + 1 + 0 + + + diff --git a/examples/Shim/SimpleRelayShim/omnetpp.ini b/examples/Shim/SimpleRelayShim/omnetpp.ini new file mode 100644 index 00000000..5c730495 --- /dev/null +++ b/examples/Shim/SimpleRelayShim/omnetpp.ini @@ -0,0 +1,79 @@ +[General] +network = SimpleRelayShim +check-signals = true +repeat = 5 +sim-time-limit = 5min +debug-on-errors = true +seed-set = ${runnumber} + +**.host1.applicationProcess1.apName = "App1" +**.host2.applicationProcess1.apName = "App2" +**.apType = "APPing" + +#Static addressing +**.host1.ipcProcessShim.ipcAddress = "1" +**.host2.ipcProcessShim.ipcAddress = "2" +**.interiorRouter.ipcProcessShim0.ipcAddress = "3" +**.interiorRouter.ipcProcessShim1.ipcAddress = "4" + +**.host1.ipcProcess1.ipcAddress = "11" +**.host2.ipcProcess1.ipcAddress = "22" +**.interiorRouter.relayIpc.ipcAddress = "33" + +**.host1.ipcProcessShim.difName = "50" +**.interiorRouter.ipcProcessShim0.difName = "50" + +**.host2.ipcProcessShim.difName = "60" +**.interiorRouter.ipcProcessShim1.difName = "60" + +**.host*.ipcProcess1.difName = "Layer11" +**.interiorRouter.relayIpc.difName = "Layer11" + +#DIF Allocator settings +**.host1.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='host1']/DA") +**.host2.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='host2']/DA") +**.interiorRouter.difAllocator.configData = xmldoc("config.xml", "Configuration/Router[@id='interiorRouter']/DA") + +#QoS Cube sets +**.ra.qoscubesData = xmldoc("config.xml", "Configuration/QoSCubesSet") + +#Specify AEPing message size +**.host1.applicationProcess1.applicationEntity.iae.size = 256B + +#Specify timeout of CreateRequest message +#**.fa.createRequestTimeout = 15s + +**.printAtEnd = true + +[Config Ping] +fingerprint = "529f-aef6" +#PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 20s +**.host1.applicationProcess1.apInst.rate = 5 +**.host1.applicationProcess1.apInst.stopAt = 200s + +[Config PingRendez] +fingerprint = "4424-27ca" +#PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.rate = 500 +**.host1.applicationProcess1.apInst.stopAt = 200s +**.host2.ipcProcess1.efcp.interrupter = true + +[Config PingWithDiffServ] +fingerprint = "00de-918f" +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.rate = 5 +**.host1.applicationProcess1.apInst.stopAt = 200s + +# make all RMTs except the ones in relay IPCs differentiate PDUs by (N)-flow +**.host*.ipcProcess1.resourceAllocator.queueAllocPolicyName = "QueuePerNFlow" +**.host*.ipcProcess1.resourceAllocator.queueIdGenName = "IDPerNFlow" + +# make relay IPCs' RMTs differentiate PDUs by their QoS +**.relayIpc.resourceAllocator.queueAllocPolicyName = "QueuePerNQoS" +**.relayIpc.resourceAllocator.queueIdGenName = "IDPerNQoS" + diff --git a/examples/Shim/SwitchShim/SwitchShim.anf b/examples/Shim/SwitchShim/SwitchShim.anf new file mode 100644 index 00000000..7121ee6f --- /dev/null +++ b/examples/Shim/SwitchShim/SwitchShim.anf @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/examples/Shim/SwitchShim/SwitchShim.ned b/examples/Shim/SwitchShim/SwitchShim.ned new file mode 100644 index 00000000..2f1f5572 --- /dev/null +++ b/examples/Shim/SwitchShim/SwitchShim.ned @@ -0,0 +1,52 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.examples.Shim.SwitchShim; + +import rina.src.CS.EthShim.Host1APShim; + +import inet.node.ethernet.Eth100M; +import inet.node.ethernet.EtherSwitch; + + +network SwitchShim +{ + @display("bgb=586,372"); + submodules: + host1: Host1APShim { + @display("p=92,83"); + } + host2: Host1APShim { + @display("p=92,252"); + } + host3: Host1APShim { + @display("p=275,83"); + } + switch: EtherSwitch { + @display("p=166,165"); + } + + connections: + switch.ethg++ <--> Eth100M <--> host1.medium; + switch.ethg++ <--> Eth100M <--> host2.medium; + switch.ethg++ <--> Eth100M <--> host3.medium; +} diff --git a/examples/Shim/SwitchShim/config.xml b/examples/Shim/SwitchShim/config.xml new file mode 100644 index 00000000..054f4dc1 --- /dev/null +++ b/examples/Shim/SwitchShim/config.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12000000 + 1000 + 24000000 + 2000 + 10000000 + 1000000 + 0.01 + 0 + 1500 + 1 + 1 + 0 + 0 + 1000000 + 500000 + 0 + 0 + 0 + + + diff --git a/examples/Shim/SwitchShim/omnetpp.ini b/examples/Shim/SwitchShim/omnetpp.ini new file mode 100644 index 00000000..06e183ba --- /dev/null +++ b/examples/Shim/SwitchShim/omnetpp.ini @@ -0,0 +1,48 @@ +[General] +network = SwitchShim +debug-on-errors = true +sim-time-limit = 5min +repeat = 5 +seed-set = ${runnumber} + +# Set IEEE802.1q encapsulation for VLANs in the switches (already set in shim IPC Processes) +**.switch.eth[*].qEncap.typename = "Ieee8021qEncap" +**.switch.eth[*].qEncap.inboundVlanFilter = "50" +**.switch.eth[*].qEncap.outboundVlanFilter = "50" + +**.host1.applicationProcess1.apName = "App1" +**.host2.applicationProcess1.apName = "App2" +**.host3.applicationProcess1.apName = "App3" +**.apType = "APPing" + +# Static addressing: lower IPC layer +**.host1.ipcProcessShim.ipcAddress = "1" +**.host2.ipcProcessShim.ipcAddress = "2" +**.host3.ipcProcessShim.ipcAddress = "3" + +# Static addressing: higher IPC layer +**.host1.ipcProcess1.ipcAddress = "11" +**.host2.ipcProcess1.ipcAddress = "12" +**.host3.ipcProcess1.ipcAddress = "13" + +**.ipcProcessShim.difName = "50" +**.ipcProcess1.difName = "Layer1" + +# DIF Allocator settings +**.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='hosts']/DA") + +# QoS Cube sets +**.ra.qoscubesData = xmldoc("config.xml", "Configuration/QoSCubesSet") + +**.ipcProcess1.*.enrollment.isSelfEnrolled = true + +[Config PingAll] +fingerprint = "c14b-0170" +# PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 10000ms +**.host2.applicationProcess1.apInst.dstApName = "App3" +**.host2.applicationProcess1.apInst.startAt = 10300ms +**.host3.applicationProcess1.apInst.dstApName = "App1" +**.host3.applicationProcess1.apInst.startAt = 10600ms +**.apInst.stopAt = 200s diff --git a/examples/Shim/ThreeHostsShim/ThreeHostsShim.anf b/examples/Shim/ThreeHostsShim/ThreeHostsShim.anf new file mode 100644 index 00000000..2856057a --- /dev/null +++ b/examples/Shim/ThreeHostsShim/ThreeHostsShim.anf @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/examples/Shim/ThreeHostsShim/ThreeHostsShim.ned b/examples/Shim/ThreeHostsShim/ThreeHostsShim.ned new file mode 100644 index 00000000..f9b10c6d --- /dev/null +++ b/examples/Shim/ThreeHostsShim/ThreeHostsShim.ned @@ -0,0 +1,45 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.examples.Shim.ThreeHostsShim; + +import rina.src.CS.EthShim.Host1APShim; +import rina.src.CS.EthShim.Host1AP2Shim; +import inet.node.ethernet.Eth100M; + + +network ThreeHostsShim +{ + submodules: + host1: Host1APShim { + @display("p=82,92"); + } + host2: Host1AP2Shim { + @display("p=231,92"); + } + host3: Host1APShim { + @display("p=380,92"); + } + connections allowunconnected: + host1.medium <--> Eth100M <--> host2.medium[0]; + host2.medium[1] <--> Eth100M <--> host3.medium; +} diff --git a/examples/Shim/ThreeHostsShim/config.xml b/examples/Shim/ThreeHostsShim/config.xml new file mode 100644 index 00000000..5d996f8f --- /dev/null +++ b/examples/Shim/ThreeHostsShim/config.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12000000 + 1000 + 24000000 + 2000 + 10000000 + 1000000 + 0.01 + 0 + 1489 + 1 + 1 + 0 + 0 + 1000000 + 500000 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + 12000000 + 1000 + 24000000 + 2000 + 10000000 + 1000000 + 0.01 + 0 + 1489 + 1 + 1 + 0 + 0 + 1000000 + 500000 + 0 + 0 + 0 + 0 + 0 + 0 + + + diff --git a/examples/Shim/ThreeHostsShim/omnetpp.ini b/examples/Shim/ThreeHostsShim/omnetpp.ini new file mode 100644 index 00000000..e2a8c75a --- /dev/null +++ b/examples/Shim/ThreeHostsShim/omnetpp.ini @@ -0,0 +1,75 @@ +[General] +network = ThreeHostsShim +debug-on-errors = true +repeat = 5 +seed-set = ${runnumber} +sim-time-limit = 5min + +**.host1.applicationProcess1.apName = "App1" +**.host2.applicationProcess1.apName = "App2" +**.host3.applicationProcess1.apName = "App3" +**.apType = "APPing" + +# Static addressing +**.host1.ipcProcessShim.ipcAddress = "11" +**.host2.ipcProcessShim0.ipcAddress = "12" +**.host2.ipcProcessShim1.ipcAddress = "13" +**.host3.ipcProcessShim.ipcAddress = "14" + +**.host1.ipcProcess1.ipcAddress = "21" +**.host2.ipcProcess1.ipcAddress = "22" +**.host3.ipcProcess1.ipcAddress = "23" + +**.host1.ipcProcessShim.difName = "50" +**.host2.ipcProcessShim0.difName = "50" +**.host2.ipcProcessShim1.difName = "60" +**.host3.ipcProcessShim.difName = "60" +**.ipcProcess1.difName = "Layer1" + +# DIF Allocator settings +**.host1.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='host1']/DA") +**.host2.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='host2']/DA") +**.host3.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='host3']/DA") + +# QoS settings +**.ra.qoscubesData = xmldoc("config.xml", "Configuration/QoSCubesSet") +**.ra.qosReqData = xmldoc("config.xml", "Configuration/QoSReqSet") + +# Relay settings, needs to be set explicitly +**.host2.ipcProcess1.relay = true + +[Config PingFC] +fingerprint = "24c6-353c" +# PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App3" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.stopAt = 140s +**.host1.applicationProcess1.apInst.interval = 1s +**.defaultMaxQLength = 150 +**.defaultThreshQLength = 100 +**.host*.ipcProcess1.efcp.efcp.rtt = 8s + +[Config PingRX] +fingerprint = "24c6-353c" +# PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App3" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.stopAt = 200s +**.host1.ipcProcess1.efcp.efcp.pduDroppingEnabled = true + +[Config Ping] +fingerprint = "24c6-353c" +# PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App3" +**.host1.applicationProcess1.apInst.startAt = 10s +**.host1.applicationProcess1.apInst.stopAt = 200s +**.host1.ipcProcess1.efcp.efcp.ecnPolicy = "DTCPECNPolicyDefault" + +[Config PingTooMuch] +**.host1.applicationProcess1.apInst.dstApName = "App3" +**.host1.applicationProcess1.apInst.startAt = 122s +**.host1.applicationProcess1.apInst.stopAt = 140s +**.host1.applicationProcess1.apInst.interval = 100ns + +**.host1.ipcProcess1.enrollment.configData = xmldoc("config.xml", "Configuration/Host[@id='host1']/Enrollment") +**.host3.ipcProcess1.enrollment.configData = xmldoc("config.xml", "Configuration/Host[@id='host3']/Enrollment") diff --git a/examples/Shim/TwoDIFsOneSwitch/TwoDIFsOneSwitch.anf b/examples/Shim/TwoDIFsOneSwitch/TwoDIFsOneSwitch.anf new file mode 100644 index 00000000..bda8442e --- /dev/null +++ b/examples/Shim/TwoDIFsOneSwitch/TwoDIFsOneSwitch.anf @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/examples/Shim/TwoDIFsOneSwitch/TwoDIFsOneSwitch.ned b/examples/Shim/TwoDIFsOneSwitch/TwoDIFsOneSwitch.ned new file mode 100644 index 00000000..daa248bd --- /dev/null +++ b/examples/Shim/TwoDIFsOneSwitch/TwoDIFsOneSwitch.ned @@ -0,0 +1,56 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.examples.Shim.TwoDIFsOneSwitch; + +import rina.src.CS.EthShim.Host1APShim; + +import inet.node.ethernet.Eth100M; +import inet.node.ethernet.EtherSwitch; + + +network TwoDIFsOneSwitch +{ + @display("bgb=366,339"); + submodules: + host1: Host1APShim { + @display("p=92,83"); + } + host2: Host1APShim { + @display("p=233,237"); + } + host3: Host1APShim { + @display("p=233,83"); + } + host4: Host1APShim { + @display("p=92,237"); + } + switch: EtherSwitch { + @display("p=163,157"); + } + + connections: + switch.ethg++ <--> Eth100M <--> host1.medium; + switch.ethg++ <--> Eth100M <--> host2.medium; + switch.ethg++ <--> Eth100M <--> host3.medium; + switch.ethg++ <--> Eth100M <--> host4.medium; +} diff --git a/examples/Shim/TwoDIFsOneSwitch/config.xml b/examples/Shim/TwoDIFsOneSwitch/config.xml new file mode 100644 index 00000000..ce21ab0b --- /dev/null +++ b/examples/Shim/TwoDIFsOneSwitch/config.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 12000000 + 1000 + 24000000 + 2000 + 10000000 + 1000000 + 0.01 + 0 + 1500 + 1 + 1 + 0 + 0 + 1000000 + 500000 + 0 + 0 + 0 + + + diff --git a/examples/Shim/TwoDIFsOneSwitch/omnetpp.ini b/examples/Shim/TwoDIFsOneSwitch/omnetpp.ini new file mode 100644 index 00000000..38e0c4ae --- /dev/null +++ b/examples/Shim/TwoDIFsOneSwitch/omnetpp.ini @@ -0,0 +1,56 @@ +[General] +network = TwoDIFsOneSwitch +debug-on-errors = true +sim-time-limit = 5min +repeat = 5 +seed-set = ${runnumber} + +# Set IEEE802.1q encapsulation for VLANs in the switches (already set in shim IPC Processes) +**.switch.eth[*].qEncap.typename = "Ieee8021qEncap" +**.switch.eth[*].qEncap.inboundVlanFilter = "50 60" +**.switch.eth[*].qEncap.outboundVlanFilter = "50 60" + +**.host1.applicationProcess1.apName = "App1" +**.host2.applicationProcess1.apName = "App2" +**.host3.applicationProcess1.apName = "App3" +**.host4.applicationProcess1.apName = "App4" +**.apType = "APPing" + +# Static addressing: lower IPC layer +**.host1.ipcProcessShim.ipcAddress = "1" +**.host2.ipcProcessShim.ipcAddress = "2" +**.host3.ipcProcessShim.ipcAddress = "1" +**.host4.ipcProcessShim.ipcAddress = "2" + +# Static addressing: higher IPC layer +**.host1.ipcProcess1.ipcAddress = "11" +**.host2.ipcProcess1.ipcAddress = "12" +**.host3.ipcProcess1.ipcAddress = "21" +**.host4.ipcProcess1.ipcAddress = "22" + +**.host1.ipcProcessShim.difName = "50" +**.host2.ipcProcessShim.difName = "50" +**.host3.ipcProcessShim.difName = "60" +**.host4.ipcProcessShim.difName = "60" + +**.host1.ipcProcess1.difName = "Layer1" +**.host2.ipcProcess1.difName = "Layer1" +**.host3.ipcProcess1.difName = "Layer2" +**.host4.ipcProcess1.difName = "Layer2" + +# DIF Allocator settings +**.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='hosts50']/DA") +**.difAllocator.configData = xmldoc("config.xml", "Configuration/Host[@id='hosts60']/DA") + +# QoS Cube sets +**.ra.qoscubesData = xmldoc("config.xml", "Configuration/QoSCubesSet") + +[Config PingAll] +fingerprint = "c14b-0170" +# PingApp setup +**.host1.applicationProcess1.apInst.dstApName = "App2" +**.host1.applicationProcess1.apInst.startAt = 10000ms +**.host3.applicationProcess1.apInst.dstApName = "App4" +**.host3.applicationProcess1.apInst.startAt = 10000ms +**.apInst.interval = 10s +**.apInst.stopAt = 200s diff --git a/src/CS/EthShim/Host1AP2Shim.ned b/src/CS/EthShim/Host1AP2Shim.ned new file mode 100644 index 00000000..51ed7d8e --- /dev/null +++ b/src/CS/EthShim/Host1AP2Shim.ned @@ -0,0 +1,70 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.src.CS.EthShim; + +import rina.src.DAF.ApplicationProcess; +import rina.src.DAF.DA.DIFAllocator; +import rina.src.DAF.IRM.IPCResourceManager; +import rina.src.DIF.IPCProcess; +import rina.src.EthShimDIF.IPCProcessShim; + +module Host1AP2Shim +{ + parameters: + @display("i=device/pc;bgb=255,400"); + @networkNode; + + gates: + inout medium[2] @loose; + + submodules: + applicationProcess1: ApplicationProcess { + @display("p=70,56"); + } + + difAllocator: DIFAllocator { + @display("p=210,56"); + } + + ipcProcessShim0: IPCProcessShim { + @display("p=70,323"); + } + + ipcProcessShim1: IPCProcessShim { + @display("p=210,323"); + } + + ipcProcess1: IPCProcess { + @display("p=133,241"); + } + + ipcResourceManager: IPCResourceManager { + @display("p=133,141"); + } + + connections allowunconnected: + ipcProcessShim0.northIo <--> ipcProcess1.southIo++; + ipcProcessShim1.northIo <--> ipcProcess1.southIo++; + ipcProcessShim0.southIo <--> medium[0]; + ipcProcessShim1.southIo <--> medium[1]; +} diff --git a/src/CS/EthShim/Host1APShim.ned b/src/CS/EthShim/Host1APShim.ned new file mode 100644 index 00000000..54ddd682 --- /dev/null +++ b/src/CS/EthShim/Host1APShim.ned @@ -0,0 +1,64 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.src.CS.EthShim; + +import rina.src.DAF.ApplicationProcess; +import rina.src.DAF.DA.DIFAllocator; +import rina.src.DAF.IRM.IPCResourceManager; +import rina.src.DIF.IPCProcess; +import rina.src.EthShimDIF.IPCProcessShim; + +module Host1APShim +{ + parameters: + @display("i=device/pc;bgb=255,400"); + @networkNode; + + gates: + inout medium @loose; + + submodules: + applicationProcess1: ApplicationProcess { + @display("p=70,56"); + } + + difAllocator: DIFAllocator { + @display("p=210,56"); + } + + ipcProcessShim: IPCProcessShim { + @display("p=133,323"); + } + + ipcProcess1: IPCProcess { + @display("p=133,241"); + } + + ipcResourceManager: IPCResourceManager { + @display("p=133,141"); + } + + connections allowunconnected: + ipcProcessShim.northIo <--> ipcProcess1.southIo++; + ipcProcessShim.southIo <--> medium; +} diff --git a/src/CS/EthShim/InteriorRouter2IntShim.ned b/src/CS/EthShim/InteriorRouter2IntShim.ned new file mode 100644 index 00000000..ccbf9e42 --- /dev/null +++ b/src/CS/EthShim/InteriorRouter2IntShim.ned @@ -0,0 +1,62 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + + +package rina.src.CS.EthShim; + +import rina.src.DAF.DA.DIFAllocator; +import rina.src.DIF.IPCProcess; +import rina.src.EthShimDIF.IPCProcessShim; + +module InteriorRouter2IntShim +{ + parameters: + @display("i=abstract/switch;bgb=290,230"); + @networkNode; + + gates: + inout medium[2]; + + submodules: + ipcProcessShim0: IPCProcessShim { + @display("p=75,169"); + } + + ipcProcessShim1: IPCProcessShim { + @display("p=215,169"); + } + + relayIpc: IPCProcess { + @display("p=145,77;i=,#FFB000"); + relay = true; + } + + difAllocator: DIFAllocator { + @display("p=65,53"); + } + + connections: + ipcProcessShim0.southIo <--> medium[0]; + ipcProcessShim1.southIo <--> medium[1]; + relayIpc.southIo++ <--> ipcProcessShim0.northIo; + relayIpc.southIo++ <--> ipcProcessShim1.northIo; +} diff --git a/src/DIF/FA/FA.cc b/src/DIF/FA/FA.cc index b3bc6237..f946f368 100644 --- a/src/DIF/FA/FA.cc +++ b/src/DIF/FA/FA.cc @@ -82,12 +82,14 @@ void FA::initSignalsAndListeners() { } -void FA::initialize() { - initPointers(); - initSignalsAndListeners(); +void FA::initialize(int stage) { + if (stage == 0) { + initPointers(); + initSignalsAndListeners(); - //Setup MyAddress - initMyAddress(); + //Setup MyAddress + initMyAddress(); + } } //XXX: Vesely - Dirty! Needs refactoring... const Address FA::getAddressFromDa(const APN& apn, bool useNeighbor, bool isMgmtFlow) { diff --git a/src/DIF/FA/FA.h b/src/DIF/FA/FA.h index 79606470..df30e7a2 100644 --- a/src/DIF/FA/FA.h +++ b/src/DIF/FA/FA.h @@ -89,7 +89,8 @@ class FA : public FABase protected: //SimpleModule overloads - virtual void initialize(); + virtual void initialize(int stage); + virtual int numInitStages() const { return 1; }; virtual void handleMessage(cMessage *msg); void initPointers(); diff --git a/src/DIF/FA/FABase.h b/src/DIF/FA/FABase.h index e6ed7f0b..f73741de 100644 --- a/src/DIF/FA/FABase.h +++ b/src/DIF/FA/FABase.h @@ -60,7 +60,8 @@ class FABase : public cSimpleModule { Address MyAddress; //SimpleModule overloads - virtual void initialize() = 0; + virtual void initialize(int stage) = 0; + virtual int numInitStages() const = 0; virtual void handleMessage(cMessage *msg) = 0; void initMyAddress(); diff --git a/src/EthShimDIF/EthShim/EthShim.cc b/src/EthShimDIF/EthShim/EthShim.cc new file mode 100644 index 00000000..5e6d2d0f --- /dev/null +++ b/src/EthShimDIF/EthShim/EthShim.cc @@ -0,0 +1,427 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "EthShimDIF/EthShim/EthShim.h" + +#include + +#include "Common/SDUData_m.h" +#include "Common/Utils.h" +#include "EthShimDIF/RINArp/RINArp.h" +#include "EthShimDIF/RINArp/RINArpPacket_m.h" +#include "EthShimDIF/ShimFA/ShimFA.h" + +#include "inet/common/IProtocolRegistrationListener.h" +#include "inet/common/ProtocolGroup.h" +#include "inet/common/ProtocolTag_m.h" +#include "inet/common/packet/Packet.h" +#include "inet/common/packet/chunk/cPacketChunk.h" +#include "inet/linklayer/common/InterfaceTag_m.h" +#include "inet/linklayer/common/MacAddressTag_m.h" +#include "inet/linklayer/common/VlanTag_m.h" +#include "inet/networklayer/common/InterfaceEntry.h" + + +const inet::Protocol EthShim::rinaEthShim = + inet::Protocol("rinaEthShim", "Ethernet shim layer for RINA"); +const int EthShim::rinaEthShimProtocolId = 0xD1F0; // Ethernet shim DIF ethertype + +Define_Module(EthShim); + +void EthShim::initialize(int stage) +{ + cSimpleModule::initialize(stage); + + if (stage == inet::INITSTAGE_LOCAL) { + ipcProcess = getParentModule(); + shimFA = getRINAModule(this, 1, {MOD_FLOWALLOC, MOD_FA}); + // TODO karlhto: maybe change, kind of a dirty way of doing this (use parameters instead?) + arp = getRINAModule(this, 1, {"arp"}); + eth = getRINAModule(this, 1, {"eth"}); + + // For tidiness, this would normally be -1 which could lead to confusion. + // TODO karlhto: consider setting to IPC address so that's used for something + eth->setInterfaceId(0); + + arp->subscribe(RINArp::completedRINArpResolutionSignal, this); + arp->subscribe(RINArp::failedRINArpResolutionSignal, this); + + vlanId = extractVlanId(ipcProcess->par("difName").stringValue()); + arp->setVlanId(vlanId); + + WATCH(numSentToNetwork); + WATCH(numReceivedFromNetwork); + WATCH_MAP(connections); + } else if (stage == inet::INITSTAGE_NETWORK_LAYER) { + // Register the RINA Ethernet shim DIF ethertype, necessary for the Ethernet Interface + if (inet::ProtocolGroup::ethertype.findProtocol(rinaEthShimProtocolId) == nullptr) + inet::ProtocolGroup::ethertype.addProtocol(rinaEthShimProtocolId, &rinaEthShim); + + // Configure the message dispatcher for lower layers + inet::registerService(rinaEthShim, nullptr, gate("ifIn")); + inet::registerProtocol(rinaEthShim, gate("ifOut"), nullptr); + } +} + +int EthShim::extractVlanId(const std::string &difName) +{ + int extractedVlanId = -1; + + try { + std::string::size_type rest; + int tmpId = std::stoi(difName, &rest, 10); + if (rest < difName.length()) + throw std::invalid_argument(""); + + // VLAN IDs 0 and 4095 (where 4095 is max, 2^12) are reserved + if (tmpId < 1 || tmpId >= 4095) + throw std::invalid_argument(""); + + extractedVlanId = tmpId; + } catch (std::invalid_argument) { + throw cRuntimeError("DIF name for shim IPCP must be a valid VLAN ID, not: %s", + difName.c_str()); + } + + return extractedVlanId; +} + +void EthShim::handleMessage(cMessage *msg) +{ + if (msg->arrivedOn("ifIn")) { + EV_INFO << "Received " << msg << " from network." << endl; + numReceivedFromNetwork++; + auto *packet = check_and_cast(msg); + handleIncomingSDU(packet); + delete packet; + } else { + EV_INFO << "Received PDU from upper layer" << endl; + auto *sdu = check_and_cast(msg); + handleOutgoingSDU(sdu, sdu->getArrivalGate()); + } +} + +void EthShim::handleOutgoingSDU(SDUData *sdu, const cGate *gate) +{ + EV_INFO << "Sending packet over ethernet" << endl; + ASSERT(gate != nullptr); + ASSERT(hasRegisteredApplication); + + auto iter = std::find_if(connections.begin(), connections.end(), + [gate](const auto &iter) { return iter.second.inGate == gate; }); + ASSERT(iter != connections.end()); + + const APN &dstApn = iter->first; + const inet::MacAddress &mac = arp->resolveAddress(dstApn); + if (mac.isUnspecified()) { + // This means that resolution has started + ConnectionEntry &entry = iter->second; + ASSERT(entry.state != ConnectionState::null); + entry.outQueue.insert(sdu); + return; + } + + sendSDUToNIC(sdu, mac); +} + +void EthShim::handleIncomingSDU(inet::Packet *packet) +{ + EV_INFO << "Passing SDU to correct gate" << endl; + + if (!hasRegisteredApplication) { + EV_WARN << "Received an SDU, but no application is registered with this shim IPC Process." + << " Discarding SDU." << endl; + return; + } + + const inet::MacAddress &srcMac = packet->getTag()->getSrcAddress(); + const APN &srcApn = arp->getAddressFor(srcMac); + if (srcApn.isUnspecified()) { + EV_WARN << "ARP does not have a valid entry for source MAC " << srcMac + << ". Discarding SDU." << endl; + return; + } + + const auto &sduWrapper = packet->peekAtFront(); + + // Duplication is required since a cPacketChunk is intended to be immutable. cPacketChunk will + // handle deletion of the original cPacket. + SDUData *sdu = check_and_cast(sduWrapper->getPacket()->dup()); + + EV_INFO << "SDU is from application with name " << srcApn << endl; + + auto &entry = connections[srcApn]; + if (entry.state == ConnectionState::null) { + EV_INFO << "No connection entry with destination application name " << srcApn + << ". Creating a new one and passing request to Flow Allocator." << endl; + entry.state = ConnectionState::recipientAllocatePending; + entry.inQueue.insert(sdu); + shimFA->createUpperFlow(srcApn); + return; + } + + if (entry.state != ConnectionState::allocated) { + EV_INFO << "Connection with application " << srcApn + << " is still pending, SDU inserted into queue." << endl; + entry.inQueue.insert(sdu); + return; + } + + EV_INFO << "Sending SDU to upper layer" << endl; + send(sdu, entry.outGate); +} + +void EthShim::sendSDUToNIC(SDUData *sdu, const inet::MacAddress &dstMac) +{ + EV_INFO << "Sending " << sdu << " to ethernet interface." << endl; + + // cPacketChunk for compatibility with the "old" OMNeT++ cPacket API, which RINA uses + auto sduWrapper = inet::makeShared(sdu); + inet::Packet *packet = new inet::Packet("SDUData"); + packet->insertAtFront(sduWrapper); + packet->addTag()->setDestAddress(dstMac); + packet->addTag()->setInterfaceId(eth->getInterfaceId()); + packet->addTag()->setProtocol(&rinaEthShim); + packet->addTag()->setVlanId(vlanId); + numSentToNetwork++; + send(packet, "ifOut"); +} + +void EthShim::sendWaitingIncomingSDUs(const APN &srcApn) +{ + auto &entry = connections[srcApn]; + ASSERT(entry.state == ConnectionState::allocated); + ASSERT(entry.outGate != nullptr); + + auto &queue = entry.inQueue; + while (!queue.isEmpty()) { + cPacket *sdu = queue.pop(); + send(sdu, entry.outGate); + } +} + +bool EthShim::createBindingsForEntry(ConnectionEntry &entry, const int portId) +{ + ASSERT(portId >= 0 && portId < ShimFA::MAX_PORTID); + ASSERT(entry.state == ConnectionState::initiatorAllocatePending || + entry.state == ConnectionState::recipientAllocatePending); + + std::ostringstream gateName; + gateName << GATE_NORTHIO_ << portId; + const std::string &tmp = gateName.str(); + const char *gateStr = tmp.c_str(); + + ASSERT(!hasGate(gateStr)); + + addGate(gateStr, cGate::INOUT, false); + cGate *shimIn = gateHalf(gateStr, cGate::INPUT); + cGate *shimOut = gateHalf(gateStr, cGate::OUTPUT); + + // This gate should already be created + if (!ipcProcess->hasGate(gateStr)) + ipcProcess->addGate(gateStr, cGate::INOUT, false); + cGate *ipcDownIn = ipcProcess->gateHalf(gateStr, cGate::INPUT); + cGate *ipcDownOut = ipcProcess->gateHalf(gateStr, cGate::OUTPUT); + + shimOut->connectTo(ipcDownOut); + ipcDownIn->connectTo(shimIn); + if (!shimOut->isConnected() || !shimIn->isConnected()) + return false; + + entry.inGate = shimIn; + entry.outGate = shimOut; + + return true; +} + +void EthShim::removeBindingsForEntry(ConnectionEntry &entry) +{ + if (entry.inGate == nullptr) + return; + + const char *gate = entry.inGate->getBaseName(); + if (ipcProcess->hasGate(gate)) { + cGate *ipcDownIn = ipcProcess->gateHalf(gate, cGate::INPUT); + ipcDownIn->disconnect(); + entry.outGate->disconnect(); + ipcProcess->deleteGate(gate); + } + + deleteGate(gate); + entry.inGate = nullptr; + entry.outGate = nullptr; +} + +bool EthShim::finalizeConnection(const APN &dstApn, const int portId) +{ + Enter_Method("finalizeConnection(%s, %d)", dstApn.c_str(), portId); + auto &entry = connections[dstApn]; + if (entry.state != ConnectionState::initiatorAllocatePending && + entry.state != ConnectionState::recipientAllocatePending) { + EV_ERROR << "Connection entry for destination application with name " << dstApn + << " cannot be finalized since state is not pending. Current state is: " + << entry.state << endl; + return false; + } + + const bool isConnected = createBindingsForEntry(entry, portId); + if (!isConnected) { + EV_ERROR << "Bindings for entry with destination address " << dstApn + << " could not be created" << endl; + deleteEntry(dstApn); + return false; + } + + entry.state = ConnectionState::allocated; + sendWaitingIncomingSDUs(dstApn); + return true; +} + +EthShim::CreateResult EthShim::createEntry(const APN &dstApn) +{ + Enter_Method("createEntry(%s)", dstApn.c_str()); + auto &entry = connections[dstApn]; + if (entry.state != ConnectionState::null) { + EV_ERROR << "ConnectionEntry already exists, something has probably gone wrong" << endl; + return CreateResult::error; + } + + entry.state = ConnectionState::initiatorAllocatePending; + + EV_INFO << "Initiating ARP resolution for destination address " << dstApn << endl; + const auto &mac = arp->resolveAddress(dstApn); + if (!mac.isUnspecified()) { + EV_INFO << "ARP entry was found!" << endl; + return CreateResult::completed; + } + + return CreateResult::pending; +} + +void EthShim::deleteEntry(const APN &dstApn) +{ + Enter_Method("deleteEntry(%s)", dstApn.c_str()); + auto &entry = connections[dstApn]; + if (entry.state == ConnectionState::null) + return; + + removeBindingsForEntry(entry); + + // Destructor of cPacketQueue will handle deletion of cPackets + connections.erase(dstApn); +} + +void EthShim::registerApplication(const APN &apni) +{ + Enter_Method("registerApplication(%s)", apni.c_str()); + EV_INFO << "Received request to register application name " << apni << " with Arp module." + << endl; + + inet::MacAddress mac = eth->getMacAddress(); + arp->addStaticEntry(mac, apni); + hasRegisteredApplication = true; +} + +void EthShim::receiveSignal(cComponent *src, simsignal_t id, cObject *obj, cObject *detail) +{ + RINArp::ArpNotification *notification = check_and_cast(obj); + + const APN &apn = notification->getApName(); + const inet::MacAddress &mac = notification->getMacAddress(); + auto &entry = connections[apn]; + if (entry.state == ConnectionState::null || + entry.state == ConnectionState::recipientAllocatePending) + return; + + if (id == RINArp::completedRINArpResolutionSignal) + arpResolutionCompleted(entry, apn, mac); + else if (id == RINArp::failedRINArpResolutionSignal) + arpResolutionFailed(apn); + else + throw cRuntimeError("Unsubscribed signalID triggered receiveSignal"); + + // Unused + (void)src; + (void)detail; +} + +void EthShim::arpResolutionCompleted(ConnectionEntry &entry, + const APN &apn, + const inet::MacAddress &mac) +{ + Enter_Method("arpResolutionCompleted(%s -> %s)", apn.c_str(), mac.str().c_str()); + + if (entry.state == ConnectionState::initiatorAllocatePending) { + shimFA->completedAddressResolution(apn); + return; + } + + auto &queue = entry.outQueue; + while (!queue.isEmpty()) { + SDUData *sdu = check_and_cast(queue.pop()); + sendSDUToNIC(sdu, mac); + } +} + +void EthShim::arpResolutionFailed(const APN &apn) +{ + Enter_Method("arpResolutionFailed(%s -> null)", apn.c_str()); + + // 1. Erase connection + deleteEntry(apn); + + // 2. Tell ShimFA, which should tell N+1 (or maybe we should let shimFA handle entry deletion? + shimFA->failedAddressResolution(apn); +} + +std::ostream &operator<<(std::ostream &os, const EthShim::ConnectionState &connectionState) +{ + // No default case so warning will be supplied if this switch is not exhaustive + switch (connectionState) { + case EthShim::ConnectionState::null: + os << "NULL"; + break; + case EthShim::ConnectionState::initiatorAllocatePending: + os << "INITIATOR ALLOCATE PENDING"; + break; + case EthShim::ConnectionState::recipientAllocatePending: + os << "RECIPIENT ALLOCATE PENDING"; + break; + case EthShim::ConnectionState::allocated: + os << "ALLOCATED"; + break; + } + return os; +} + +std::ostream &operator<<(std::ostream &os, const EthShim::ConnectionEntry &connectionEntry) +{ + os << "State: " << connectionEntry.state; + os << ", Gate: "; + if (connectionEntry.inGate != nullptr) + os << connectionEntry.inGate->getBaseName(); + else + os << "undefined"; + os << ", In-queue size: " << connectionEntry.inQueue.getLength(); + os << ", Out-queue size: " << connectionEntry.outQueue.getLength(); + return os; +} diff --git a/src/EthShimDIF/EthShim/EthShim.h b/src/EthShimDIF/EthShim/EthShim.h new file mode 100644 index 00000000..827cb51b --- /dev/null +++ b/src/EthShimDIF/EthShim/EthShim.h @@ -0,0 +1,221 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once + +#include + +#include "Common/APN.h" + +#include "inet/common/InitStages.h" +#include "inet/common/Protocol.h" + +// INET forward declarations (should be less overhead than including everything every time) +namespace inet { + class Packet; + class MacAddress; + class InterfaceEntry; +}; + +class RINArp; +class RINArpPacket; +class ShimFA; +class SDUData; + +/** + * Implements the main element of the RINA Ethernet shim DIF + */ +class EthShim : public cSimpleModule, public cListener +{ + public: + /// enum used for returning status of a create request + enum class CreateResult { error, pending, completed }; + + /// enum used for recording the state of a connection + enum class ConnectionState { + null, + initiatorAllocatePending, + recipientAllocatePending, + allocated + }; + + /// Information required for connection with a remote system + struct ConnectionEntry { + ConnectionState state = ConnectionState::null; + cGate *inGate = nullptr; + cGate *outGate = nullptr; + cPacketQueue outQueue = cPacketQueue("Queue for outgoing packets"); + cPacketQueue inQueue = cPacketQueue("Queue for incoming packets"); + }; + + static const inet::Protocol rinaEthShim; + static const int rinaEthShimProtocolId; + + private: + /// map containing connection states with remote systems + std::map connections; + + /// State variable for whether an application is connected + bool hasRegisteredApplication = false; + + /// VLAN ID to use for outgoing messages + int vlanId; + + /// Pointers to important modules + cModule *ipcProcess = nullptr; + RINArp *arp = nullptr; + ShimFA *shimFA = nullptr; + inet::InterfaceEntry *eth = nullptr; + + /// Statistics + long numSentToNetwork = 0; + long numReceivedFromNetwork = 0; + + public: + /** @brief Empty constructor for the time being */ + EthShim() = default; + + /** + * @brief Registers name of the application using this shim IPCP in static ARP entry + * @param apn Name of registered application + */ + void registerApplication(const APN &apn); + + /** + * @brief Finalises a connection entry + * @param dstApn Name of application to be reached + * @param portId Port ID used as handle for registered application, used in gate names + * @return true if the bindings were successfully created, false otherwise + */ + [[nodiscard]] bool finalizeConnection(const APN &dstApn, int portId); + + /** + * @brief Creates a connection state entry, and starts ARP resolution + * @param dstApn Name of application to be reached + * @return CreateResult::completed if ARP returned an address immediately, ::pending if ARP + * resolution was initiated, and ::failed if a connection entry already exists + */ + [[nodiscard]] CreateResult createEntry(const APN &dstApn); + + /** + * @brief Deletes a connection entry + * @param dstApn Name of "connected" application + */ + void deleteEntry(const APN &dstApn); + + private: + /// cSimpleModule overrides + + /** @brief Initialises module pointers and subscribes to ARP signals */ + void initialize(int stage) override; + int numInitStages() const override { return inet::NUM_INIT_STAGES; } + + /** @brief Passes packets to correct helper function based on input */ + void handleMessage(cMessage *msg) override; + + + /// Initialisation + + /** + * @brief Extracts VLAN ID from DIF name + * @param difName Name of DIF, to use as VLAN ID + * @return VLAN ID as an integer, parsed from string + */ + int extractVlanId(const std::string &difName); + + + /// Packet handling + + /** + * @brief Handles SDUs from upper layer, resolving gate to destination address + * @param sdu SDU from upper layer + * @param gate Input gate that received sdu + */ + void handleOutgoingSDU(SDUData *sdu, const cGate *gate); + + /** + * @brief Handles SDU from network, resolving connection entry from source MAC Address + * @param sdu SDU from ethernet interface + */ + void handleIncomingSDU(inet::Packet *packet); + + /** + * @brief Wraps an SDU in a `cPacketChunk` before sending it on to the Ethernet interface + * @param sdu SDU to encapsulate and send + * @param dstMac MAC address of destination host + */ + void sendSDUToNIC(SDUData *sdu, const inet::MacAddress &dstMac); + + /** + * @brief Sends waiting SDUs in queue, + * @param srcApn The name of the application that the SDUs originated from + */ + void sendWaitingIncomingSDUs(const APN &srcApn); + + + /// Entry management + + /** + * @brief Creates gates and bindings for an entry, and populates its gate pointers + * @param entry Entry to create gates for + * @param portId Used as gate ID + * @return true if gates were successfully created, false otherwise + */ + [[nodiscard]] bool createBindingsForEntry(ConnectionEntry &entry, const int portId); + + /** + * @brief Removes gates and bindings for an entry + * @param entry Entry to remove gates from + */ + void removeBindingsForEntry(ConnectionEntry &entry); + + + /// cListener overrides and ARP signal handlers + + /** + * @brief Retrieves `ArpNotification` objects, passing them to correct helper function + * @param source Source module of signal (unused) + * @param id Id of signal, either completedRINArpResolution or failedRINArpResolution + * @param obj ArpNotification object to be passed on + * @param details Unused + */ + void receiveSignal(cComponent *source, simsignal_t id, cObject *obj, cObject *details) override; + + /** + * @brief Sends waiting outgoing packets or finishes flow allocation, based on entry state + * @param entry Relevant connection entry + * @param apn Destination application name associated with the connection entry + * @param mac Destination MAC address of interface to reach + */ + void arpResolutionCompleted(ConnectionEntry &entry, + const APN &apn, + const inet::MacAddress &mac); + + /** + * @brief Handles a failed ARP resolve, removing connection entry and notifying Flow Allocator + * @param apn Destination application name associated with a connection entry to be removed + */ + void arpResolutionFailed(const APN &apn); +}; + +std::ostream &operator<<(std::ostream &os, const EthShim::ConnectionState &connectionState); +std::ostream &operator<<(std::ostream &os, const EthShim::ConnectionEntry &connectionEntry); diff --git a/src/EthShimDIF/EthShim/EthShim.ned b/src/EthShimDIF/EthShim/EthShim.ned new file mode 100644 index 00000000..a1d0c7f6 --- /dev/null +++ b/src/EthShimDIF/EthShim/EthShim.ned @@ -0,0 +1,32 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.src.EthShimDIF.EthShim; + +simple EthShim +{ + parameters: + @display("i=block/routing"); + gates: + input ifIn; + output ifOut; +} diff --git a/src/EthShimDIF/IPCProcessShim.ned b/src/EthShimDIF/IPCProcessShim.ned new file mode 100644 index 00000000..2a9d468c --- /dev/null +++ b/src/EthShimDIF/IPCProcessShim.ned @@ -0,0 +1,82 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.src.EthShimDIF; + +import rina.src.EthShimDIF.ShimFA.ShimFlowAllocator; +import rina.src.EthShimDIF.EthShim.EthShim; +import rina.src.EthShimDIF.RINArp.RINArp; + +import inet.common.MessageDispatcher; +import inet.linklayer.contract.IEthernetInterface; + +module IPCProcessShim +{ + parameters: + @display("bgb=402,300;i=misc/square,#008000,50;i2=status/connect"); + string ipcAddress; + string difName; + string apName = default(ipcAddress + "_" + difName); + + gates: + inout northIo; + inout southIo; + submodules: + shim: EthShim { + parameters: + @display("p=201,127"); + } + + flowAllocator: ShimFlowAllocator { + parameters: + @display("p=320,127"); + } + + arp: RINArp { + parameters: + @display("p=82,127"); + } + + sl: MessageDispatcher { + parameters: + @display("p=201,184;b=200,5,,,,1"); + } + + eth: like IEthernetInterface { + parameters: + @display("p=201,240,row,60;q=txQueue"); + qEncap.typename = "Ieee8021qEncap"; + qEncap.inboundVlanIdFilter = difName; + qEncap.outboundVlanIdFilter = difName; + // Explicitly set this to empty + interfaceTableModule = ""; + } + + connections allowunconnected: + arp.ifOut --> sl.in++; + arp.ifIn <-- sl.out++; + shim.ifOut --> sl.in++; + shim.ifIn <-- sl.out++; + eth.upperLayerOut --> sl.in++; + eth.upperLayerIn <-- sl.out++; + eth.phys <--> { @display("m=s"); } <--> southIo; +} diff --git a/src/EthShimDIF/RINArp/RINArp.cc b/src/EthShimDIF/RINArp/RINArp.cc new file mode 100644 index 00000000..fafbbe8b --- /dev/null +++ b/src/EthShimDIF/RINArp/RINArp.cc @@ -0,0 +1,373 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "EthShimDIF/RINArp/RINArp.h" + +#include "Common/Utils.h" +#include "EthShimDIF/RINArp/RINArpPacket_m.h" + +#include "inet/common/packet/Packet.h" +#include "inet/common/IProtocolRegistrationListener.h" +#include "inet/common/ProtocolTag_m.h" +#include "inet/common/ModuleAccess.h" +#include "inet/linklayer/common/InterfaceTag_m.h" +#include "inet/linklayer/common/MacAddressTag_m.h" +#include "inet/linklayer/common/VlanTag_m.h" +#include "inet/linklayer/ethernet/EtherFrame_m.h" + + +Define_Module(RINArp); +Register_Abstract_Class(RINArp::ArpNotification); + +// Static signal entries +const simsignal_t RINArp::initiatedRINArpResolutionSignal = + registerSignal("initiatedRINArpResolution"); +const simsignal_t RINArp::completedRINArpResolutionSignal = + registerSignal("completedRINArpResolution"); +const simsignal_t RINArp::failedRINArpResolutionSignal = registerSignal("failedRINArpResolution"); +const simsignal_t RINArp::sentRINArpReqSignal = registerSignal("sentRINArpReq"); +const simsignal_t RINArp::sentRINArpReplySignal = registerSignal("sentRINArpReply"); + +RINArp::~RINArp() +{ + for (auto &elem : arpCache) { + auto *entry = elem.second; + cancelAndDelete(entry->timer); + delete entry; + } + + if (thisHost.second != nullptr) + delete thisHost.second; +} + +void RINArp::initialize(int stage) +{ + cSimpleModule::initialize(stage); + + if (stage == inet::INITSTAGE_LOCAL) { + eth = getRINAModule(this, 1, {"eth"}); + + retryTimeout = par("retryTimeout"); + retryCount = par("retryCount"); + cacheTimeout = par("cacheTimeout"); + + WATCH(numResolutions); + WATCH(numFailedResolutions); + WATCH(numRequestsSent); + WATCH(numRepliesSent); + } else if (stage == inet::INITSTAGE_NETWORK_LAYER) { + inet::registerService(inet::Protocol::arp, nullptr, gate("ifIn")); + inet::registerProtocol(inet::Protocol::arp, gate("ifOut"), nullptr); + } +} + +bool RINArp::addStaticEntry(const inet::MacAddress &mac, const APN &apn) +{ + Enter_Method("addStaticEntry(%s, %s)", mac.str().c_str(), apn.c_str()); + + ASSERT(!mac.isUnspecified()); + ASSERT(!apn.isUnspecified()); + + // Is already in use + if (!thisHost.first.isUnspecified()) + return false; + + auto *entry = new ArpCacheEntry(); + entry->macAddress = mac; + entry->timer = nullptr; + entry->lastUpdate = simTime(); + thisHost = std::make_pair(apn, entry); + return true; +} + +void RINArp::deleteStaticEntry() +{ + Enter_Method("deleteStaticEntry()"); + if (!thisHost.first.isUnspecified()) + thisHost.first.setName(""); + + if (thisHost.second != nullptr) { + auto *entry = thisHost.second; + cancelAndDelete(entry->timer); + entry->timer = nullptr; + delete entry; + } +} + +void RINArp::setVlanId(int vlanId) +{ + this->vlanId = vlanId; +} + +bool RINArp::addressRecognized(const APN &destApn) +{ + if (destApn == thisHost.first) + return true; + else + return false; +} + +void RINArp::flush() +{ + while (!arpCache.empty()) { + auto i = arpCache.begin(); + auto *entry = i->second; + cancelAndDelete(entry->timer); + entry->timer = nullptr; + delete entry; + arpCache.erase(i); + } +} + +void RINArp::handleMessage(cMessage *msg) +{ + if (msg->isSelfMessage()) + requestTimeout(msg); + else { + auto *packet = check_and_cast(msg); + processArpPacket(packet); + } +} + +void RINArp::updateArpCache(ArpCacheEntry *entry, const inet::MacAddress &macAddress) +{ + if (entry->pending) { + entry->pending = false; + cancelAndDelete(entry->timer); + entry->timer = nullptr; + entry->numRetries = 0; + } + entry->macAddress = macAddress; + entry->lastUpdate = simTime(); + ArpNotification signal(entry->myIter->first, macAddress); + emit(completedRINArpResolutionSignal, &signal); +} + +const inet::MacAddress &RINArp::resolveAddress(const APN &apn) +{ + Enter_Method("resolveAddress(%s)", apn.c_str()); + + EV << "Asked to resolve destination address " << apn << endl; + + auto it = arpCache.find(apn); + if (it == arpCache.end()) { + // No ARP cache entry found, need to send ARP request + auto *entry = new ArpCacheEntry(); + auto where = arpCache.insert(arpCache.begin(), std::make_pair(apn, entry)); + entry->myIter = where; + initiateArpResolution(entry); + return inet::MacAddress::UNSPECIFIED_ADDRESS; + } else if (it->second->pending) { + return inet::MacAddress::UNSPECIFIED_ADDRESS; + } else if (it->second->lastUpdate + cacheTimeout >= simTime()) { + return it->second->macAddress; + } + + // If entry exists but has been timed out + auto *entry = it->second; + initiateArpResolution(entry); + return inet::MacAddress::UNSPECIFIED_ADDRESS; +} + +const APN &RINArp::getAddressFor(const inet::MacAddress &mac) const +{ + Enter_Method_Silent(); + + if (mac.isUnspecified()) + return APN::UNSPECIFIED_APN; + + simtime_t now = simTime(); + for (const auto &elem : arpCache) + if (elem.second->macAddress == mac && elem.second->lastUpdate + cacheTimeout >= now) + return elem.first; + + return APN::UNSPECIFIED_APN; +} + +void RINArp::initiateArpResolution(ArpCacheEntry *entry) +{ + const APN &apn = entry->myIter->first; + entry->pending = true; + entry->numRetries = 0; + entry->lastUpdate = SIMTIME_ZERO; + entry->macAddress = inet::MacAddress::UNSPECIFIED_ADDRESS; + sendArpRequest(apn); + + cMessage *msg = entry->timer = new cMessage("ARP timeout"); + msg->setContextPointer(entry); + scheduleAt(simTime() + retryTimeout, msg); + + numResolutions++; + ArpNotification signal(apn, inet::MacAddress::UNSPECIFIED_ADDRESS); + emit(initiatedRINArpResolutionSignal, &signal); +} + +void RINArp::sendArpRequest(const APN &dstApn) +{ + const APN &srcApn = thisHost.first; // Registered application + const inet::MacAddress &srcMac = thisHost.second->macAddress; + + ASSERT(!srcMac.isUnspecified()); + ASSERT(!srcApn.isUnspecified()); + + const int apnLen = std::max(srcApn.length(), dstApn.length()); + + const auto &arp = inet::makeShared(); + arp->setChunkLength(inet::B(ARP_BASE_LEN + apnLen * 2)); + arp->setApnLength(apnLen); + + arp->setOpcode(ARP_REQUEST); + arp->setSrcMacAddress(srcMac); + arp->setSrcApName(srcApn); + arp->setDstApName(dstApn); + + inet::Packet *packet = new inet::Packet("arpREQ"); + packet->insertAtFront(arp); + packet->addTag()->setDestAddress(inet::MacAddress::BROADCAST_ADDRESS); + packet->addTag()->setInterfaceId(eth->getInterfaceId()); + packet->addTag()->setProtocol(&inet::Protocol::arp); + packet->addTag()->setVlanId(vlanId); + + EV_INFO << "Sending " << packet << " to network." << endl; + send(packet, "ifOut"); + + numRequestsSent++; + emit(sentRINArpReqSignal, 1L); +} + +void RINArp::processArpPacket(inet::Packet *packet) +{ + EV_INFO << "Received " << packet << " from network." << endl; + const auto &arp = packet->peekAtFront(); + + const inet::MacAddress &srcMac = arp->getSrcMacAddress(); + const APN &srcApn = arp->getSrcApName(); + const APN &dstApn = arp->getDstApName(); + + ASSERT(!srcMac.isUnspecified()); + ASSERT(!srcApn.isUnspecified()); + ASSERT(!dstApn.isUnspecified()); + + EV_TRACE << arp << " has source MAC " << srcMac << " and APN " << srcApn << endl; + + bool mergeFlag = false; + auto it = arpCache.find(srcApn); + if (it != arpCache.end()) { + ArpCacheEntry *entry = it->second; + updateArpCache(entry, srcMac); + mergeFlag = true; + } + + if (addressRecognized(dstApn)) { + if (!mergeFlag) { + ArpCacheEntry *entry; + if (it != arpCache.end()) { + entry = it->second; + } else { + entry = new ArpCacheEntry(); + auto where = arpCache.insert(arpCache.begin(), std::make_pair(srcApn, entry)); + entry->myIter = where; + entry->pending = false; + entry->timer = nullptr; + entry->numRetries = 0; + } + + updateArpCache(entry, srcMac); + } + + EV_TRACE << arp << " was for us! "; + + switch (arp->getOpcode()) { + case ARP_REQUEST: { + EV_TRACE << "Sending ARP reply with MAC destination: " << srcMac + << ", source: " << thisHost.second->macAddress << endl; + + const auto &arpReply = inet::makeShared(); + // Protocol address length will remain the same. We need to + // swap the addresses, however. + arpReply->setChunkLength(arp->getChunkLength()); + arpReply->setApnLength(arp->getApnLength()); + arpReply->setDstMacAddress(srcMac); + arpReply->setDstApName(srcApn); + arpReply->setSrcMacAddress(thisHost.second->macAddress); + arpReply->setSrcApName(dstApn); + arpReply->setOpcode(ARP_REPLY); + + inet::Packet *outPacket = new inet::Packet("arpReply"); + outPacket->insertAtFront(arpReply); + outPacket->addTag()->setDestAddress(srcMac); + outPacket->addTag()->setInterfaceId(eth->getInterfaceId()); + outPacket->addTag()->setProtocol(&inet::Protocol::arp); + outPacket->addTag()->setVlanId(vlanId); + + EV_INFO << "Sending " << outPacket << " to network protocol." << endl; + send(outPacket, "ifOut"); + numRepliesSent++; + emit(sentRINArpReplySignal, 1L); + + break; + } + case ARP_REPLY: { + EV_DETAIL << "Discarding packet." << endl; + break; + } + case ARP_RARP_REQUEST: + throw cRuntimeError("RARP request received but not supported"); + case ARP_RARP_REPLY: + throw cRuntimeError("RARP reply received but not supported"); + default: + throw cRuntimeError( + "Unsuported opcode %d from received Arp" + " packet", + arp->getOpcode()); + } + } else { + EV_INFO << "Address " << dstApn << " not recognized, " + << "dropping packet." << endl; + } + + delete packet; +} + +void RINArp::requestTimeout(cMessage *selfmsg) +{ + auto *entry = (ArpCacheEntry *)selfmsg->getContextPointer(); + entry->numRetries++; + if (entry->numRetries < retryCount) { + const APN &dstApn = entry->myIter->first; + EV_INFO << "ARP request for " << dstApn << " timed out, resending." << endl; + sendArpRequest(dstApn); + scheduleAt(simTime() + retryTimeout, selfmsg); + return; + } + + // If max retryCount hit + delete selfmsg; + + EV << "ARP timed out with max retry count " << retryCount << " for destination address " + << entry->myIter->first << endl; + ArpNotification signal(entry->myIter->first, inet::MacAddress::UNSPECIFIED_ADDRESS); + emit(failedRINArpResolutionSignal, &signal); + arpCache.erase(entry->myIter); + delete entry; + numFailedResolutions++; +} diff --git a/src/EthShimDIF/RINArp/RINArp.h b/src/EthShimDIF/RINArp/RINArp.h new file mode 100644 index 00000000..11e2e4a9 --- /dev/null +++ b/src/EthShimDIF/RINArp/RINArp.h @@ -0,0 +1,163 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once + +#include + +#include "Common/APN.h" + +#include "inet/linklayer/common/MacAddress.h" + +namespace inet { + class Packet; + class InterfaceEntry; +}; + +class RINArpPacket; + +/** + * RINArp + * + * This module is more or less a RINA-specific version of the ARP + * implementation done in INET. + */ +class RINArp : public cSimpleModule +{ + public: + struct ArpCacheEntry; + using ArpCache = std::map; + + /** + * Used for resolving path for APNs + */ + struct ArpCacheEntry + { + inet::MacAddress macAddress; + bool pending = false; + simtime_t lastUpdate; + int numRetries = 0; + cMessage *timer = nullptr; + ArpCache::iterator myIter; + }; + + /** + * Notifications for changes in ARP, like a completed ARP resolution + */ + class ArpNotification : public cObject + { + private: + const APN apName; + const inet::MacAddress macAddress; + + public: + ArpNotification(const APN &apName, const inet::MacAddress &macAddress) + : apName(apName), macAddress(macAddress) + { + } + + [[nodiscard]] const APN &getApName() const { return apName; } + [[nodiscard]] const inet::MacAddress &getMacAddress() const { return macAddress; } + }; + + /** @brief Signals for publishing ARP state changes */ + static const simsignal_t initiatedRINArpResolutionSignal; + static const simsignal_t completedRINArpResolutionSignal; + static const simsignal_t failedRINArpResolutionSignal; + static const simsignal_t sentRINArpReqSignal; + static const simsignal_t sentRINArpReplySignal; + + private: + /// Retry settings for ARP cache entries + simtime_t retryTimeout; + int retryCount = 0; + + /// ID of VLAN to use for ougtoing packets + int vlanId; + + /// Some watchable numbers + long numResolutions = 0; + long numFailedResolutions = 0; + long numRequestsSent = 0; + long numRepliesSent = 0; + + /// How long an ARP entry should stay in cache + simtime_t cacheTimeout; + + /// ARP cache entries + ArpCache arpCache; + std::pair thisHost; ///< Naming information for this host + + /// Bound Ethernet interface + inet::InterfaceEntry *eth; + + public: + RINArp() = default; + ~RINArp() override; + + /** @brief Attempts to resolve an application name, may send ARP_REQ packet */ + const inet::MacAddress &resolveAddress(const APN &apn); + + /** @brief Finds the APN name of an entry by its MAC address */ + const APN &getAddressFor(const inet::MacAddress &mac) const; + + /** @brief Adds this host's information, necessary for N+1 registration */ + bool addStaticEntry(const inet::MacAddress &mac, const APN &apn); + + /** @brief Removes static entry for connected host */ + void deleteStaticEntry(); + + /** @brief Sets VLAN ID for outgoing messages */ + void setVlanId(int vlanId); + + protected: + /** @brief Processes ARP packets, adds entry if destination is same as apname */ + void processArpPacket(inet::Packet *packet); + + /** @brief Handles timeout selfmessages */ + void requestTimeout(cMessage *msg); + + /** @brief Removes all entries of ARP cache */ + void flush(); + + /** @brief Readies pending entry, sends ARP_REQ, and starts timeout timer */ + void initiateArpResolution(ArpCacheEntry *entry); + + /** @brief Updates an ARP cache entry with an address */ + void updateArpCache(ArpCacheEntry *entry, const inet::MacAddress &mac); + + /** @brief Checks if specified APN is same as in static entry */ + bool addressRecognized(const APN &apn); + + /** @brief Sends an ARP request addressed to specified APN */ + void sendArpRequest(const APN &apn); + + + /// cSimpleModule overrides + + /** @brief Initialises parameters and out gate */ + void initialize(int stage) override; + int numInitStages() const override { return inet::NUM_INIT_STAGES; } + + /** @brief Handles selfmessages and messages from ethernet shim module */ + void handleMessage(cMessage *msg) override; +}; diff --git a/src/EthShimDIF/RINArp/RINArp.ned b/src/EthShimDIF/RINArp/RINArp.ned new file mode 100644 index 00000000..e67f9366 --- /dev/null +++ b/src/EthShimDIF/RINArp/RINArp.ned @@ -0,0 +1,44 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.src.EthShimDIF.RINArp; + +simple RINArp { + parameters: + double retryTimeout @unit("s") = default(1s); + int retryCount = default(3); + double cacheTimeout @unit("s") = default(120s); + @display("i=block/layer"); + @signal[sentRINArpReq](type=long); + @signal[sentRINArpReply](type=long); + @signal[initiatedRINArpResolution](type=RINArp::ArpNotification); + @signal[completedRINArpResolution](type=RINArp::ArpNotification); + @signal[failedRINArpResolution](type=RINArp::ArpNotification); + @statistic[sentRINArpReq](title="ARP requests sent"; record=count,vector); + @statistic[sentRINArpReply](title="ARP replies sent"; record=count,vector); + @statistic[initiatedRINArpResolution](title="ARP resolutions initiated"; record=count); + @statistic[completedRINArpResolution](title="ARP resolutions completed"; record=count); + @statistic[failedRINArpResolution](title="ARP resolutions failed"; record=count); + gates: + input ifIn @labels(RINArpPacket+Ieee802Ctrl); + output ifOut @labels(RINArpPacket+Ieee802Ctrl); +} diff --git a/src/EthShimDIF/RINArp/RINArpPacket.msg b/src/EthShimDIF/RINArp/RINArpPacket.msg new file mode 100644 index 00000000..446635d1 --- /dev/null +++ b/src/EthShimDIF/RINArp/RINArpPacket.msg @@ -0,0 +1,59 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// @author karlhto +// This is heavily inspired by INET's ARP protocol machine. + +cplusplus {{ +#include "inet/common/packet/chunk/FieldsChunk.h" +#include "inet/linklayer/common/MacAddress.h" +#include "Common/APN.h" + +#define ARP_BASE_LEN 14 // 2 * mac addresses (12) + apnLength + opcode +}} + +class noncobject APN; + +class noncobject inet::MacAddress; +class noncobject inet::FieldsChunk; + + +enum ARPOpcode +{ + ARP_REQUEST = 1; + ARP_REPLY = 2; + ARP_RARP_REQUEST = 3; + ARP_RARP_REPLY = 4; +} + +// +// RINArpPacket. This type of ARPPacket is specialised for RINA, which uses +// variable length addresses. +class RINArpPacket extends inet::FieldsChunk +{ + uint8_t apnLength; + uint8_t opcode @enum(ARPOpcode); + inet::MacAddress srcMacAddress; + APN srcApName; + inet::MacAddress dstMacAddress; + APN dstApName; +} diff --git a/src/EthShimDIF/ShimFA/ShimFA.cc b/src/EthShimDIF/ShimFA/ShimFA.cc new file mode 100644 index 00000000..c1d61d87 --- /dev/null +++ b/src/EthShimDIF/ShimFA/ShimFA.cc @@ -0,0 +1,279 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "EthShimDIF/ShimFA/ShimFA.h" + +#include "Common/ConnectionId.h" +#include "Common/Flow.h" +#include "Common/RINASignals.h" +#include "Common/Utils.h" +#include "DIF/FA/NFlowTable.h" +#include "EthShimDIF/EthShim/EthShim.h" +#include "EthShimDIF/RINArp/RINArp.h" +#include "EthShimDIF/ShimFA/ShimFAI.h" + +Define_Module(ShimFA); + +/* + * Initialisation functionality + */ +ShimFA::ShimFA() : FABase::FABase() +{ + qos.setQosId("unreliable"); +} + +ShimFA::~ShimFA() = default; + +void ShimFA::initialize(int stage) +{ + if (stage == inet::INITSTAGE_LOCAL) { + shimIpcProcess = getModuleByPath("^.^"); + if (shimIpcProcess == nullptr) + throw cRuntimeError("ShimFA not used in any IPC Process"); + + arp = getRINAModule(this, 2, {"arp"}); + shim = getRINAModule(this, 2, {"shim"}); + nFlowTable = getRINAModule(this, 1, {MOD_NFLOWTABLE}); + + // Registering an application is not supported in RINASim since any upper + // layer connected IPCP/AP is implicitly registered. We still need the AP name + // of the upper layer. Unfortunately pretty hacky solution for the time being, + // but finds connected IPC process + const cGate *dstGate = shimIpcProcess->gate("northIo$o")->getPathEndGate(); + if (dstGate == nullptr) { + EV_ERROR + << "Shim IPC not connected to overlying application. It will be able to receive " + << "ARP requests, but will never send ARP reply" << endl; + return; + } + + connectedApplication = dstGate->getOwnerModule(); + if (!connectedApplication->hasPar("apName")) + throw cRuntimeError( + "Shim IPC process not connected to overlying IPC/Application Process"); + + // displayString for IPC Process + initMyAddress(); + } else if (stage == inet::INITSTAGE_TRANSPORT_LAYER) { + // Needs to be done in initialisation phase since registration is implicit in RINASim. + registeredApplication = APN(connectedApplication->par("apName").stringValue()); + + // Registers application with static entry in Arp, needs to be called after stage 0 to + // guarantee allocation of MAC address + shim->registerApplication(registeredApplication); + } +} + +void ShimFA::handleMessage(cMessage *msg) +{ + // self message is the only valid message here + delete msg; +} + +bool ShimFA::createUpperFlow(const APN &dstApn) +{ + Enter_Method("createUpperFlow(%s)", dstApn.c_str()); + + EV << "Received request to forward allocation request to N+1, with source address " << dstApn + << endl; + + ConnectionId connId; + // TODO replace this with QoS ID that we accept + connId.setQoSId(qos.getQosId()); + + Flow *flow = new Flow(registeredApplication, dstApn); + flow->setQosCube(qos); + flow->setConId(connId); + flow->setDstNeighbor(dstApn); + flow->setSrcNeighbor(registeredApplication); + + ShimFAI *fai = createFAI(flow); + nFlowTable->insertNew(flow); + flow->setSrcPortId(fai->getLocalPortId()); + nFlowTable->setFaiToFlow(fai, flow); + nFlowTable->changeAllocStatus(flow, NFlowTableEntry::TRANSFER); + + return fai->receiveCreateRequest(); +} + +bool ShimFA::receiveAllocateRequest(Flow *flow) +{ + Enter_Method("receiveAllocateRequest()"); + + EV << "Received allocation request for flow with destination address " + << flow->getDstApni().getApn() << endl; + + const auto &apName = flow->getDstApni().getApn(); + + // If an entry already exists for specified application, use that + // NOTE: this creates problems with the current implementation of flow allocation, since the + // resource allocator of the N+1 IPCP will have checked the existence of a satisfactory flow + // already. With other words, we are essentially forced to make sure that the N+1 IPCP asks + // for the very same QoS cube that the shim IPCP supports. + auto nft = nFlowTable->findEntryByApnisAndQosId(registeredApplication, apName, qos.getQosId()); + if (nft != nullptr) { + auto *fai = static_cast(nft->getFai()); + flow->setSrcPortId(fai->getLocalPortId()); + return true; + } + + const auto result = shim->createEntry(apName); + if (result == EthShim::CreateResult::error) + return false; + + ConnectionId connId; + connId.setQoSId(qos.getQosId()); + flow->setConId(connId); + flow->setQosCube(qos); + + ShimFAI *fai = createFAI(flow); + nFlowTable->insertNew(flow); + flow->setSrcPortId(fai->getLocalPortId()); + nFlowTable->setFaiToFlow(fai, flow); + nFlowTable->changeAllocStatus(flow, NFlowTableEntry::ALLOC_PEND); + + if (result == EthShim::CreateResult::completed) + return fai->receiveAllocateRequest(); + + return true; +} + +bool ShimFA::receiveDeallocateRequest(Flow *flow) +{ + Enter_Method("receiveDeallocateRequest()"); + EV << "Received deallocation request for flow with destination APN " << endl; + + auto *entry = nFlowTable->findEntryByFlow(flow); + if (entry == nullptr) + return false; + + deinstantiateFai(flow); + return true; +} + +void ShimFA::completedAddressResolution(const APN &dstApn) +{ + Enter_Method("completedAddressResolution(%s)", dstApn.getName().c_str()); + EV << "Completed address resolution for " << dstApn << endl; + auto nft = + nFlowTable->findEntryByApnisAndQosId(registeredApplication, dstApn, qos.getQosId()); + if (nft == nullptr) { + EV << "No such pending flow found" << endl; + return; + } else if (nft->getAllocateStatus() == NFlowTableEntry::TRANSFER) { + EV << "Flow already exists, continue sending" << endl; + } + + Flow *flow = nft->getFlow(); + nFlowTable->changeAllocStatus(flow, NFlowTableEntry::TRANSFER); + auto *fai = static_cast(nft->getFai()); + fai->receiveAllocateRequest(); +} + +void ShimFA::failedAddressResolution(const APN &dstApn) +{ + Enter_Method("failedAddressResolution(%s)", dstApn.getName().c_str()); + auto *entry = + nFlowTable->findEntryByApnisAndQosId(registeredApplication, dstApn, qos.getQosId()); + deinstantiateFai(entry->getFlow()); +} + +ShimFAI *ShimFA::createFAI(Flow *flow) +{ + cModuleType *type = cModuleType::get("rina.src.EthShimDIF.ShimFA.ShimFAI"); + unsigned int portId = intrand(MAX_PORTID, RANDOM_NUMBER_GENERATOR); + + std::ostringstream ostr; + ostr << "fai_" << portId; + + cModule *module = type->create(ostr.str().c_str(), getParentModule()); + module->par(PAR_LOCALPORTID) = portId; + module->finalizeParameters(); + module->buildInside(); + module->scheduleStart(simTime()); + module->callInitialize(); + + auto *fai = check_and_cast(module); + fai->postInitialize(this, flow, shim); + + // Make created module listen to allocation responses from upper IPCP + connectedApplication->subscribe(SIG_AERIBD_AllocateResponsePositive, fai); + connectedApplication->subscribe(SIG_AERIBD_AllocateResponseNegative, fai); + + return fai; +} + +void ShimFA::deinstantiateFai(Flow *flow) +{ + // Might be kind of redundant to find entry _again_ but whatever, we're trying to comply with + // the FABase API + auto *entry = nFlowTable->findEntryByFlow(flow); + ShimFAI *fai = static_cast(entry->getFai()); + + // This should honestly have some return value + fai->receiveDeallocateRequest(); +} + +// Not sure what to do with this function as of yet. This is called by upper +// layer, but not checked. It's possible at least a subset of the flow +// allocation policies should be implemented +bool ShimFA::invokeNewFlowRequestPolicy(Flow *) +{ + return true; +} + +/* Mandatory but unused function definitions due to FABase (most of these are _very_ specific + * to the normal IPCP FA, so should probably exclusively belong there) */ +bool ShimFA::setOriginalAddresses(Flow *) +{ + return false; +} + +bool ShimFA::setNeighborAddresses(Flow *) +{ + return false; +} + +bool ShimFA::receiveMgmtAllocateRequest(Flow *) +{ + throw cRuntimeError("ShimFA does not support creation of management flows"); +} + +bool ShimFA::receiveMgmtAllocateRequest(APNamingInfo, APNamingInfo) +{ + throw cRuntimeError("ShimFA does not support creation of management flows"); +} + +bool ShimFA::receiveMgmtAllocateFinish(APNIPair *) +{ + throw cRuntimeError("ShimFA does not support creation of management flows"); +} + +void ShimFA::receiveNM1FlowCreated(Flow *) +{ + throw cRuntimeError("ShimFA should be on medium, no NM1 flow possible"); +} + +bool ShimFA::receiveCreateFlowRequestFromRibd(Flow *) +{ + throw cRuntimeError("ShimFA should not need to communicate with RIBd"); +} diff --git a/src/EthShimDIF/ShimFA/ShimFA.h b/src/EthShimDIF/ShimFA/ShimFA.h new file mode 100644 index 00000000..ddca8320 --- /dev/null +++ b/src/EthShimDIF/ShimFA/ShimFA.h @@ -0,0 +1,120 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once + +#include + +#include "Common/QoSCube.h" +#include "DIF/FA/FABase.h" + +#include "inet/common/InitStages.h" + +class ShimFAI; +class EthShim; +class RINArp; + +/** + * Shim specific Flow Allocator. + * + * Flow Allocator Instances are still allocated, but only source port information is kept. + */ +class ShimFA : public FABase +{ + private: + /// Pointers to important modules + cModule *shimIpcProcess = nullptr; + cModule *connectedApplication = nullptr; + RINArp *arp = nullptr; + EthShim *shim = nullptr; + + APN registeredApplication; ///< apName of "registered" application + + QoSCube qos; ///< Unreliable QoS cube declaration + + public: + ShimFA(); + ~ShimFA() override; + + /** + * @brief Attempts to initialise a new flow + * @param flow A flow object pre-populated with destination and source APNIs and QoSReq + * @return true if FA instance created and connection entry was either created or pending, + * false if creation of instance or connection entry fails + */ + bool receiveAllocateRequest(Flow *flow) override; + + /** + * @brief Attempts to deallocate a new flow + * @param flow The flow object corresponding with a Flow Allocator Instance + * @return true if flow was successfully deallocated, false otherwise + */ + bool receiveDeallocateRequest(Flow *flow) override; + + /** + * @brief Finalises a pending connection and sends a positive allocation response to N+1 IPCP + * @param apn Application name associated with destination application of a flow table entry + */ + void completedAddressResolution(const APN &apn); + + /** + * @brief Cancels a pending flow or deallocates an allocated flow + * @param apn Application name associated with destination application of a flow table entry + */ + void failedAddressResolution(const APN &apn); + + /** + * @brief Deallocates a FAI and removes the corresponding flow and connection entry + * @param flow Flow corresponding to the FAI and connection entry (in shim module) + */ + void deinstantiateFai(Flow *flow) override; + + /** + * @brief Attempts to allocate a flow from NM1 IPCP + * + * Called when a frame from an unknown host arrives at the shim module. + * + * @param apn Application name of the connection source + * @return true if a flow allocator instance is successfully created, false otherwise + */ + bool createUpperFlow(const APN &apn); + + /// Provided for compatibility ? + bool invokeNewFlowRequestPolicy(Flow *flow) override; + + /// These are all unused in shim layer, but still implemented as required by FABase + bool receiveMgmtAllocateRequest(Flow *mgmtflow) override; + bool receiveMgmtAllocateRequest(APNamingInfo src, APNamingInfo dst) override; + bool receiveMgmtAllocateFinish(APNIPair *apnip) override; + void receiveNM1FlowCreated(Flow *flow) override; + bool receiveCreateFlowRequestFromRibd(Flow *flow) override; + bool setOriginalAddresses(Flow *flow) override; + bool setNeighborAddresses(Flow *flow) override; + + private: + ShimFAI *createFAI(Flow *flow); + + /// SimpleModule overrides + void initialize(int stage) override; + int numInitStages() const override { return inet::NUM_INIT_STAGES; } + void handleMessage(cMessage *msg) override; +}; diff --git a/src/EthShimDIF/ShimFA/ShimFA.ned b/src/EthShimDIF/ShimFA/ShimFA.ned new file mode 100644 index 00000000..2e0fba04 --- /dev/null +++ b/src/EthShimDIF/ShimFA/ShimFA.ned @@ -0,0 +1,34 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.src.EthShimDIF.ShimFA; + +simple ShimFA +{ + parameters: + @display("i=block/fork"); + + @signal[FAI-AllocateRequest](type=Flow?); + @signal[FAI-DeallocateRequest](type=Flow?); + @signal[FAI-AllocateResponsePositive](type=Flow?); + @signal[FAI-AllocateResponseNegative](type=Flow?); +} diff --git a/src/EthShimDIF/ShimFA/ShimFAI.cc b/src/EthShimDIF/ShimFA/ShimFAI.cc new file mode 100644 index 00000000..b6a3c710 --- /dev/null +++ b/src/EthShimDIF/ShimFA/ShimFAI.cc @@ -0,0 +1,143 @@ +#include "EthShimDIF/ShimFA/ShimFAI.h" + +#include "Common/RINASignals.h" +#include "DIF/FA/FANotifierBase.h" +#include "DIF/FA/NFlowTable.h" +#include "EthShimDIF/EthShim/EthShim.h" +#include "EthShimDIF/ShimFA/ShimFA.h" + +Define_Module(ShimFAI); + +// The N+1 IPCP expects a response from this IPCP's RIBd instead of from the Flow Allocator that +// it specifically requested a flow from for some reason, so we have to emit that signal. +const simsignal_t ShimFAI::ribdCreateFlowResponsePositive = + registerSignal(SIG_RIBD_CreateFlowResponsePositive); + +ShimFAI::ShimFAI() : localPortId(VAL_UNDEF_PORTID) +{ +} + +ShimFAI::~ShimFAI() = default; + +void ShimFAI::initialize() +{ + localPortId = static_cast(par(PAR_LOCALPORTID)); +} + +void ShimFAI::postInitialize(ShimFA *fa, Flow *flow, EthShim *shim) +{ + // Should the main storage space of the flow be FAI or nFlowTable? + this->fa = fa; + this->flow = flow; + this->shim = shim; +} + +void ShimFAI::handleMessage(cMessage *msg) +{ + delete msg; +} + +int ShimFAI::getLocalPortId() const +{ + return localPortId; +} + +bool ShimFAI::receiveAllocateRequest() +{ + Enter_Method("receiveAllocateRequest()"); + bool res = shim->finalizeConnection(flow->getDstApni().getApn(), localPortId); + if (res) { + EV << "Successfully allocated flow" << endl; + emit(ribdCreateFlowResponsePositive, flow); + } + + return res; +} + +bool ShimFAI::receiveCreateRequest() +{ + // TODO (karlhto): Check table state + Enter_Method("receiveCreateRequest()"); + emit(allocateRequestSignal, flow); + + return true; +} + +bool ShimFAI::receiveCreateResponseNegative() +{ + return false; +} + +bool ShimFAI::receiveAllocateResponsePositive() +{ + Enter_Method("receiveAllocateResponsePositive()"); + EV << "Received positive allocation response! Sending pending SDUs" << endl; + NFlowTable *nft = fa->getNFlowTable(); + NFlowTableEntry *nfte = nft->findEntryByFlow(flow); + if (nfte == nullptr) { + EV_ERROR << "No table entry for this flow found!" << endl; + return false; + } + + auto &dstApn = flow->getDstApni().getApn(); + bool res = shim->finalizeConnection(dstApn, localPortId); + if (!res) { + // TODO (karlhto): deallocate flows here + EV_ERROR << "Failed to create entry!" << endl; + return false; + } + + nft->changeAllocStatus(flow, NFlowTableEntry::TRANSFER); + return true; +} + +void ShimFAI::receiveAllocateResponseNegative() +{ + Enter_Method("receiveAllocateResponseNegative()"); +} + + +void ShimFAI::receiveSignal(cComponent *src, simsignal_t id, cObject *obj, cObject *detail) +{ + Flow *flow = check_and_cast(obj); + if (flow != this->flow) + return; + + if (id == FANotifierBase::allocateResponsePositiveSignal) + receiveAllocateResponsePositive(); + else if (id == FANotifierBase::allocateResponseNegativeSignal) + receiveAllocateResponseNegative(); + + (void)detail; + (void)src; +} + +std::string ShimFAI::str() const +{ + std::stringstream os; + os << "FAI>" << endl << "\tlocal Port-ID: " << this->localPortId << endl; + return os.str(); +} + +// Irrelevant functions +bool ShimFAI::receiveCreateResponsePositive(Flow *) +{ + return false; +} +bool ShimFAI::receiveDeallocateRequest() +{ + return false; +} +void ShimFAI::receiveDeleteRequest(Flow *) +{ +} +void ShimFAI::receiveDeleteResponse() +{ +} + +void ShimFAI::receiveCreateFlowResponsePositiveFromNminusOne() +{ +} +void ShimFAI::receiveCreateFlowResponseNegativeFromNminusOne() +{ +} diff --git a/src/EthShimDIF/ShimFA/ShimFAI.h b/src/EthShimDIF/ShimFA/ShimFAI.h new file mode 100644 index 00000000..96b9c77c --- /dev/null +++ b/src/EthShimDIF/ShimFA/ShimFAI.h @@ -0,0 +1,81 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once + +#include + +#include "DIF/FA/FAIBase.h" + +class ShimFA; +class EthShim; + +class ShimFAI : public FAIBase, public cListener +{ + public: + // Some public objects? + enum ConnectionState { UNALLOCATED, ALLOCATE_PENDING, ALLOCATED }; + + // oh god why + static const simsignal_t ribdCreateFlowResponsePositive; + + private: + // Important protected objects + int localPortId; + + cMessage *creReqTimer; + ShimFA *fa; + EthShim *shim; + Flow *flow; + + public: + // Public functions + ShimFAI(); + ~ShimFAI() override; + + std::string str() const override; + + // Need the rest of them + bool receiveAllocateRequest() override; + bool receiveAllocateResponsePositive() override; + void receiveAllocateResponseNegative() override; + bool receiveCreateRequest() override; + bool receiveCreateResponsePositive(Flow *flow) override; + bool receiveCreateResponseNegative() override; + bool receiveDeallocateRequest() override; + void receiveDeleteRequest(Flow *flow) override; + void receiveDeleteResponse() override; + + void receiveCreateFlowResponsePositiveFromNminusOne() override; + void receiveCreateFlowResponseNegativeFromNminusOne() override; + + void postInitialize(ShimFA *fa, Flow *flow, EthShim *shim); + int getLocalPortId() const; + + protected: + // cSimpleModule overrides + void initialize() override; + void handleMessage(cMessage *msg) override; + + // cListener override + void receiveSignal(cComponent *src, simsignal_t id, cObject *obj, cObject *detail) override; +}; diff --git a/src/EthShimDIF/ShimFA/ShimFAI.ned b/src/EthShimDIF/ShimFA/ShimFAI.ned new file mode 100644 index 00000000..df978601 --- /dev/null +++ b/src/EthShimDIF/ShimFA/ShimFAI.ned @@ -0,0 +1,43 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.src.EthShimDIF.ShimFA; + +simple ShimFAI +{ + parameters: + @display("i=block/rxtx"); + @signal[RIBd-CreateFlowResponsePositive](type=Flow?); + @signal[FAI-DeallocateRequest](type=Flow?); + @signal[FAI-AllocateRequest](type=Flow?); + @signal[FAI-AllocateResponsePositive](type=Flow?); + @signal[FAI-AllocateResponseNegative](type=Flow?); + @signal[FAI-CreateFlowRequest](type=Flow?); + @signal[FAI-DeleteFlowRequest](type=Flow?); + @signal[FAI-CreateFlowResponsePositive](type=Flow?); + @signal[FAI-CreateFlowResponseNegative](type=Flow?); + @signal[FAI-DeleteFlowResponse](type=Flow?); + + int localPortId = default(-1); + + //double createRequestTimeout @unit(s) = default(10s); +} diff --git a/src/EthShimDIF/ShimFA/ShimFlowAllocator.ned b/src/EthShimDIF/ShimFA/ShimFlowAllocator.ned new file mode 100644 index 00000000..c258dd71 --- /dev/null +++ b/src/EthShimDIF/ShimFA/ShimFlowAllocator.ned @@ -0,0 +1,38 @@ +// The MIT License (MIT) +// +// Copyright (c) 2014-2016 Brno University of Technology, PRISTINE project +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package rina.src.EthShimDIF.ShimFA; + +import rina.src.DIF.FA.NFlowTable; + +module ShimFlowAllocator { + parameters: + @display("i=block/fork;bgb=424,357"); + submodules: + nFlowTable: NFlowTable { + @display("p=167,64"); + } + + fa: ShimFA { + @display("p=75,64"); + } +}