Skip to content
Snippets Groups Projects
Commit e472c6ea authored by Adam Dunkels's avatar Adam Dunkels
Browse files
parents eeb25b96 942ba1f7
No related branches found
No related tags found
No related merge requests found
......@@ -94,7 +94,15 @@ data_packet_forward(struct multihop_conn *multihop,
rt = route_lookup(dest);
if(rt == NULL) {
if(c->queued_data != NULL) {
queuebuf_free(c->queued_data);
}
PRINTF("data_packet_forward: queueing data, sending rreq\n");
c->queued_data = queuebuf_new_from_packetbuf();
rimeaddr_copy(&c->queued_data_dest, dest);
route_discovery_discover(&c->route_discovery_conn, dest, PACKET_TIMEOUT);
return NULL;
} else {
route_refresh(rt);
......@@ -106,15 +114,21 @@ data_packet_forward(struct multihop_conn *multihop,
static void
found_route(struct route_discovery_conn *rdc, const rimeaddr_t *dest)
{
struct route_entry *rt;
struct mesh_conn *c = (struct mesh_conn *)
((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn));
PRINTF("found_route\n");
if(c->queued_data != NULL &&
rimeaddr_cmp(dest, &c->queued_data_dest)) {
queuebuf_to_packetbuf(c->queued_data);
queuebuf_free(c->queued_data);
c->queued_data = NULL;
if(multihop_send(&c->multihop, dest)) {
rt = route_lookup(dest);
if (rt != NULL) {
multihop_resend(&c->multihop, &rt->nexthop);
c->cb->sent(c);
} else {
c->cb->timedout(c);
......@@ -175,15 +189,7 @@ mesh_send(struct mesh_conn *c, const rimeaddr_t *to)
could_send = multihop_send(&c->multihop, to);
if(!could_send) {
if(c->queued_data != NULL) {
queuebuf_free(c->queued_data);
}
PRINTF("mesh_send: queueing data, sending rreq\n");
c->queued_data = queuebuf_new_from_packetbuf();
rimeaddr_copy(&c->queued_data_dest, to);
route_discovery_discover(&c->route_discovery_conn, to,
PACKET_TIMEOUT);
PRINTF("mesh_send: could not send\n");
return 0;
}
c->cb->sent(c);
......
......@@ -94,11 +94,10 @@ data_packet_received(struct unicast_conn *uc, const rimeaddr_t *from)
} else {
nexthop = NULL;
if(c->cb->forward) {
nexthop = c->cb->forward(c, &sender, &receiver,
from, packetbuf_attr(PACKETBUF_ATTR_HOPS));
packetbuf_set_attr(PACKETBUF_ATTR_HOPS,
packetbuf_attr(PACKETBUF_ATTR_HOPS) + 1);
nexthop = c->cb->forward(c, &sender, &receiver,
from, packetbuf_attr(PACKETBUF_ATTR_HOPS) - 1);
}
if(nexthop) {
PRINTF("forwarding to %d.%d\n", nexthop->u8[0], nexthop->u8[1]);
......@@ -133,6 +132,9 @@ multihop_send(struct multihop_conn *c, const rimeaddr_t *to)
return 0;
}
packetbuf_compact();
packetbuf_set_addr(PACKETBUF_ADDR_ERECEIVER, to);
packetbuf_set_addr(PACKETBUF_ADDR_ESENDER, &rimeaddr_node_addr);
packetbuf_set_attr(PACKETBUF_ATTR_HOPS, 1);
nexthop = c->cb->forward(c, &rimeaddr_node_addr, to, NULL, 0);
if(nexthop == NULL) {
......@@ -141,12 +143,15 @@ multihop_send(struct multihop_conn *c, const rimeaddr_t *to)
} else {
PRINTF("multihop_send: sending data towards %d.%d\n",
nexthop->u8[0], nexthop->u8[1]);
packetbuf_set_addr(PACKETBUF_ADDR_ERECEIVER, to);
packetbuf_set_addr(PACKETBUF_ADDR_ESENDER, &rimeaddr_node_addr);
packetbuf_set_attr(PACKETBUF_ATTR_HOPS, 1);
unicast_send(&c->c, nexthop);
return 1;
}
}
/*---------------------------------------------------------------------------*/
void
multihop_resend(struct multihop_conn *c, const rimeaddr_t *nexthop)
{
unicast_send(&c->c, nexthop);
}
/*---------------------------------------------------------------------------*/
/** @} */
......@@ -104,6 +104,7 @@ void multihop_open(struct multihop_conn *c, uint16_t channel,
const struct multihop_callbacks *u);
void multihop_close(struct multihop_conn *c);
int multihop_send(struct multihop_conn *c, const rimeaddr_t *to);
void multihop_resend(struct multihop_conn *c, const rimeaddr_t *nexthop);
#endif /* __MULTIHOP_H__ */
/** @} */
......
......@@ -56,43 +56,14 @@ AUTOSTART_PROCESSES(&testcoffee_process);
/*---------------------------------------------------------------------------*/
static int
coffee_gc_test(void)
{
int i;
cfs_remove("alpha");
cfs_remove("beta");
for (i = 0; i < 100; i++) {
if (i & 1) {
if(cfs_coffee_reserve("alpha", random_rand() & 0xffff) < 0) {
return -i;
}
cfs_remove("beta");
} else {
if(cfs_coffee_reserve("beta", 93171) < 0) {
return -1;
}
cfs_remove("alpha");
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
static int
coffee_file_test(void)
coffee_test_basic(void)
{
int error;
int wfd, rfd, afd;
unsigned char buf[256], buf2[11];
int r, i, j, total_read;
unsigned offset;
unsigned char buf[256];
int r;
cfs_remove("T1");
cfs_remove("T2");
cfs_remove("T3");
wfd = rfd = afd = -1;
......@@ -103,130 +74,207 @@ coffee_file_test(void)
/* Test 1: Open for writing. */
wfd = cfs_open("T1", CFS_WRITE);
if(wfd < 0) {
FAIL(-1);
FAIL(1);
}
/* Test 2: Write buffer. */
/* Test 2 and 3: Write buffer. */
r = cfs_write(wfd, buf, sizeof(buf));
if(r < 0) {
FAIL(-2);
FAIL(2);
} else if(r < sizeof(buf)) {
FAIL(-3);
FAIL(3);
}
/* Test 3: Deny reading. */
/* Test 4: Deny reading. */
r = cfs_read(wfd, buf, sizeof(buf));
if(r >= 0) {
FAIL(-4);
FAIL(4);
}
/* Test 4: Open for reading. */
/* Test 5: Open for reading. */
rfd = cfs_open("T1", CFS_READ);
if(rfd < 0) {
FAIL(-5);
FAIL(5);
}
/* Test 5: Write to read-only file. */
/* Test 6: Write to read-only file. */
r = cfs_write(rfd, buf, sizeof(buf));
if(r >= 0) {
FAIL(-6);
FAIL(6);
}
/* Test 7: Read the buffer written in Test 2. */
/* Test 7 and 8: Read the buffer written in Test 2. */
memset(buf, 0, sizeof(buf));
r = cfs_read(rfd, buf, sizeof(buf));
if(r < 0) {
FAIL(-8);
FAIL(7);
} else if(r < sizeof(buf)) {
printf("r=%d\n", r);
FAIL(-9);
FAIL(8);
}
/* Test 8: Verify that the buffer is correct. */
/* Test 9: Verify that the buffer is correct. */
for(r = 0; r < sizeof(buf); r++) {
if(buf[r] != r) {
printf("r=%d. buf[r]=%d\n", r, buf[r]);
FAIL(-10);
FAIL(9);
}
}
/* Test 9: Seek to beginning. */
/* Test 10: Seek to beginning. */
if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
FAIL(-11);
FAIL(10);
}
/* Test 10: Write to the log. */
/* Test 11 and 12: Write to the log. */
r = cfs_write(wfd, buf, sizeof(buf));
if(r < 0) {
FAIL(-12);
FAIL(11);
} else if(r < sizeof(buf)) {
FAIL(-13);
FAIL(12);
}
/* Test 11: Read the data from the log. */
/* Test 13 and 14: Read the data from the log. */
cfs_seek(rfd, 0, CFS_SEEK_SET);
memset(buf, 0, sizeof(buf));
r = cfs_read(rfd, buf, sizeof(buf));
if(r < 0) {
FAIL(-14);
FAIL(14);
} else if(r < sizeof(buf)) {
FAIL(-15);
FAIL(15);
}
/* Test 12: Verify that the data is correct. */
/* Test 16: Verify that the data is correct. */
for(r = 0; r < sizeof(buf); r++) {
if(buf[r] != r) {
FAIL(-16);
FAIL(16);
}
}
/* Test 13: Write a reversed buffer to the file. */
/* Test 17 to 20: Write a reversed buffer to the file. */
for(r = 0; r < sizeof(buf); r++) {
buf[r] = sizeof(buf) - r - 1;
}
if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
FAIL(-17);
FAIL(17);
}
r = cfs_write(wfd, buf, sizeof(buf));
if(r < 0) {
FAIL(-18);
FAIL(18);
} else if(r < sizeof(buf)) {
FAIL(-19);
FAIL(19);
}
if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) {
FAIL(-20);
FAIL(20);
}
/* Test 14: Read the reversed buffer. */
/* Test 21 and 22: Read the reversed buffer. */
cfs_seek(rfd, 0, CFS_SEEK_SET);
memset(buf, 0, sizeof(buf));
r = cfs_read(rfd, buf, sizeof(buf));
if(r < 0) {
FAIL(-21);
FAIL(21);
} else if(r < sizeof(buf)) {
printf("r = %d\n", r);
FAIL(-22);
FAIL(22);
}
/* Test 15: Verify that the data is correct. */
/* Test 23: Verify that the data is correct. */
for(r = 0; r < sizeof(buf); r++) {
if(buf[r] != sizeof(buf) - r - 1) {
FAIL(-23);
FAIL(23);
}
}
cfs_close(rfd);
error = 0;
end:
cfs_close(wfd);
cfs_close(rfd);
return error;
}
/*---------------------------------------------------------------------------*/
static int
coffee_test_append(void)
{
int error;
int afd;
unsigned char buf[256], buf2[11];
int r, i, j, total_read;
#define APPEND_BYTES 1000
#define BULK_SIZE 10
cfs_remove("T2");
/* Test 1 and 2: Append data to the same file many times. */
for(i = 0; i < APPEND_BYTES; i += BULK_SIZE) {
afd = cfs_open("T3", CFS_WRITE | CFS_APPEND);
if(afd < 0) {
FAIL(1);
}
for(j = 0; j < BULK_SIZE; j++) {
buf[j] = 1 + ((i + j) & 0x7f);
}
if((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) {
printf("r=%d\n", r);
FAIL(2);
}
cfs_close(afd);
}
/* Test 3-6: Read back the data written previously and verify that it
is correct. */
afd = cfs_open("T3", CFS_READ);
if(afd < 0) {
FAIL(3);
}
total_read = 0;
while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
for(j = 0; j < r; j++) {
if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
FAIL(4);
}
}
total_read += r;
}
if(r < 0) {
FAIL(5);
}
if(total_read != APPEND_BYTES) {
FAIL(6);
}
cfs_close(afd);
error = 0;
end:
cfs_close(afd);
return error;
}
/*---------------------------------------------------------------------------*/
static int
coffee_test_modify(void)
{
int error;
int wfd;
unsigned char buf[256];
int r, i;
unsigned offset;
cfs_remove("T3");
wfd = -1;
if(cfs_coffee_reserve("T3", FILE_SIZE) < 0) {
FAIL(1);
}
if(cfs_coffee_reserve("T2", FILE_SIZE) < 0) {
FAIL(-24);
if(cfs_coffee_configure_log("T3", FILE_SIZE / 2, 11) < 0) {
FAIL(2);
}
/* Test 16: Test multiple writes at random offset. */
for(r = 0; r < 100; r++) {
wfd = cfs_open("T2", CFS_WRITE | CFS_READ);
if(wfd < 0) {
FAIL(-25);
FAIL(3);
}
offset = random_rand() % FILE_SIZE;
......@@ -236,88 +284,101 @@ coffee_file_test(void)
}
if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
FAIL(-26);
FAIL(4);
}
if(cfs_write(wfd, buf, sizeof(buf)) != sizeof(buf)) {
FAIL(-27);
FAIL(5);
}
if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
FAIL(-28);
FAIL(6);
}
memset(buf, 0, sizeof(buf));
if(cfs_read(wfd, buf, sizeof(buf)) != sizeof(buf)) {
FAIL(-29);
FAIL(7);
}
for(i = 0; i < sizeof(buf); i++) {
if(buf[i] != i) {
printf("buf[%d] != %d\n", i, buf[i]);
FAIL(-30);
FAIL(8);
}
}
}
/* Test 17: Append data to the same file many times. */
#define APPEND_BYTES 1000
#define BULK_SIZE 10
for(i = 0; i < APPEND_BYTES; i += BULK_SIZE) {
afd = cfs_open("T3", CFS_WRITE | CFS_APPEND);
if(afd < 0) {
FAIL(-31);
}
for(j = 0; j < BULK_SIZE; j++) {
buf[j] = 1 + ((i + j) & 0x7f);
}
if((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) {
printf("r=%d\n", r);
FAIL(-32);
}
cfs_close(afd);
}
error = 0;
end:
cfs_close(wfd);
return error;
}
/*---------------------------------------------------------------------------*/
static int
coffee_test_gc(void)
{
int i;
/* Test 18: Read back the data written in Test 17 and verify that it
is correct. */
afd = cfs_open("T3", CFS_READ);
if(afd < 0) {
FAIL(-33);
}
total_read = 0;
while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
for(j = 0; j < r; j++) {
if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
FAIL(-34);
cfs_remove("alpha");
cfs_remove("beta");
for (i = 0; i < 100; i++) {
if (i & 1) {
if(cfs_coffee_reserve("alpha", random_rand() & 0xffff) < 0) {
return i;
}
cfs_remove("beta");
} else {
if(cfs_coffee_reserve("beta", 93171) < 0) {
return i;
}
cfs_remove("alpha");
}
total_read += r;
}
if(r < 0) {
FAIL(-35);
}
if(total_read != APPEND_BYTES) {
FAIL(-36);
}
cfs_close(afd);
error = 0;
end:
cfs_close(wfd); cfs_close(rfd); cfs_close(afd);
return error;
return 0;
}
/*---------------------------------------------------------------------------*/
static void
print_result(const char *test_name, int result)
{
printf("%s: ", test_name);
if(result == 0) {
printf("OK\n");
} else {
printf("ERROR (test %d)\n", result);
}
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(testcoffee_process, ev, data)
{
int start;
int result;
PROCESS_BEGIN();
start = clock_seconds();
printf("Coffee format: %d\n", cfs_coffee_format());
printf("Coffee file test: %d\n", coffee_file_test());
printf("Coffee garbage collection test: %d\n", coffee_gc_test());
printf("Test time: %d seconds\n", (int)(clock_seconds() - start));
printf("Coffee test started\n");
result = cfs_coffee_format();
print_result("Formatting", result);
result = coffee_test_basic();
print_result("Basic operations", result);
result = coffee_test_append();
print_result("File append", result);
result = coffee_test_modify();
print_result("File modification", result);
result = coffee_test_gc();
print_result("Garbage collection", result);
printf("Coffee test finished. Duration: %d seconds\n",
(int)(clock_seconds() - start));
PROCESS_END();
}
......
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project>../apps/mrm</project>
<project>../apps/mspsim</project>
<project>../apps/avrora</project>
<project>../apps/native_gateway</project>
<simulation>
<title>test</title>
<delaytime>0</delaytime>
<randomseed>generated</randomseed>
<motedelay_us>0</motedelay_us>
<radiomedium>
se.sics.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>100.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<motetype>
se.sics.cooja.mspmote.SkyMoteType
<identifier>sky1</identifier>
<description>Sky Mote Type #1</description>
<source>../../../examples/sky/test-coffee.c</source>
<commands>make clean TARGET=sky
make test-coffee.sky TARGET=sky</commands>
<firmware>../../../examples/sky/test-coffee.sky</firmware>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyByteRadio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkySerial</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyLED</moteinterface>
</motetype>
<mote>
se.sics.cooja.mspmote.SkyMote
<motetype_identifier>sky1</motetype_identifier>
<breakpoints />
<interface_config>
se.sics.cooja.interfaces.Position
<x>97.11078411573273</x>
<y>56.790978919276014</y>
<z>0.0</z>
</interface_config>
<interface_config>
se.sics.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.SimControl
<width>248</width>
<z>3</z>
<height>200</height>
<location_x>0</location_x>
<location_y>0</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.Visualizer
<plugin_config>
<skin>Mote IDs</skin>
<skin>Log output: printf()'s</skin>
</plugin_config>
<width>246</width>
<z>2</z>
<height>170</height>
<location_x>1</location_x>
<location_y>200</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.LogListener
<plugin_config>
<filter />
</plugin_config>
<width>846</width>
<z>1</z>
<height>209</height>
<location_x>2</location_x>
<location_y>370</location_y>
<minimized>false</minimized>
</plugin>
<plugin>
se.sics.cooja.plugins.ScriptRunner
<plugin_config>
<script>TIMEOUT(80000);
fileOK = null;
gcOK = null;
while (fileOK == null || gcOK == null) {
YIELD();
if (msg.startsWith('Coffee file test: 0')) {
fileOK = true;
} else if (msg.startsWith('Coffee file test')) {
fileOK = false;
} else if (msg.startsWith('Coffee garbage collection test: 0')) {
gcOK = true;
} else if (msg.startsWith('Coffee garbage collection test')) {
gcOK = false;
}
}
if (gcOK == false) {
log.log("coffee garbage collection failed\n");
}
if (fileOK == false) {
log.log("coffee file test failed\n");
}
if (!fileOK || !gcOK) {
log.testFailed();
} else {
log.testOK();
}</script>
<active>true</active>
</plugin_config>
<width>601</width>
<z>0</z>
<height>370</height>
<location_x>247</location_x>
<location_y>0</location_y>
<minimized>false</minimized>
</plugin>
</simconf>
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/mrm</project>
<project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/mspsim</project>
<project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/avrora</project>
<project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/serial_socket</project>
<project EXPORT="discard">[CONTIKI_DIR]/tools/cooja/apps/collect-view</project>
<simulation>
<title>test</title>
<delaytime>0</delaytime>
<randomseed>generated</randomseed>
<motedelay_us>0</motedelay_us>
<radiomedium>
se.sics.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>100.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
se.sics.cooja.mspmote.SkyMoteType
<identifier>sky1</identifier>
<description>Sky Mote Type #1</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/sky/test-coffee.c</source>
<commands EXPORT="discard">make clean TARGET=sky
make test-coffee.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/sky/test-coffee.sky</firmware>
<moteinterface>se.sics.cooja.interfaces.Position</moteinterface>
<moteinterface>se.sics.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>se.sics.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyByteRadio</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>se.sics.cooja.mspmote.interfaces.SkyLED</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
se.sics.cooja.interfaces.Position
<x>97.11078411573273</x>
<y>56.790978919276014</y>
<z>0.0</z>
</interface_config>
<interface_config>
se.sics.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>sky1</motetype_identifier>
</mote>
</simulation>
<plugin>
se.sics.cooja.plugins.SimControl
<width>248</width>
<z>0</z>
<height>200</height>
<location_x>0</location_x>
<location_y>0</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.Visualizer
<plugin_config>
<skin>se.sics.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>se.sics.cooja.plugins.skins.LogVisualizerSkin</skin>
<viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 28.717468985697536 3.3718373461127142</viewport>
</plugin_config>
<width>246</width>
<z>3</z>
<height>170</height>
<location_x>1</location_x>
<location_y>200</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.LogListener
<plugin_config>
<filter />
</plugin_config>
<width>846</width>
<z>2</z>
<height>209</height>
<location_x>2</location_x>
<location_y>370</location_y>
</plugin>
<plugin>
se.sics.cooja.plugins.ScriptRunner
<plugin_config>
<script>TIMEOUT(80000);
fileOK = null;
gcOK = null;
while (fileOK == null || gcOK == null) {
YIELD();
if(msg.contains("ERROR")) {
log.log(msg);
log.testFailed();
}
if (msg.startsWith('Coffee test finished')) {
log.testOK();
}
}</script>
<active>true</active>
</plugin_config>
<width>601</width>
<z>1</z>
<height>370</height>
<location_x>247</location_x>
<location_y>0</location_y>
</plugin>
</simconf>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment