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");
+ }
+}