Net-runner

Working with the Net-runner-engine and routing

1 year ago by Seva D. (sabrinarempel7@gmail.com)

In this short article we're gonna write some code using $ Net-runner-engine$  and see how IP masks are used to handle routing. Lets create a simple network with some switches and hubs:

const Simulator = require('net-runner-engine');
const path = require('path');

const { Network, Hub, Switch, Host, TCPClient, TCPServer } = Simulator;

const dstDir = path.resolve(__dirname, 'switch-hub');

const net = new Network({
  animeLen: 3,
  populateIP: true,
});

const swtch = new Switch(net, { name: 'Switch', x: 400, y: 400 });

const swtchHosts = Array.from({ length: 4 }, (_, i) => new Host(net, { name: `SwitchHost${i}`, y: 0, x: 400*i }));

swtchHosts.map((e, i) => e.connect(swtch, { sourceIP: `192.168.1.${i}` }));

const hub = new Hub(net, { name: 'Hub', x: 400, y: 800 });

const hubHosts = Array.from({ length: 4 }, (_, i) => new Host(net, { name: `HubHost${i}`, y: 1200, x: 400*i }));

hubHosts.map((e, i) => e.connect(hub, { sourceIP: `192.168.1.${i + 20}` }));

hub.connect(swtch);

hubHosts[0].setupApplication(new TCPClient({
  addr: '192.168.1.0',
  port: 8080,
  dataRate: '50Mbps',
  packetSize: 5*1024,
}));

swtchHosts[0].setupApplication(new TCPServer({
  port: 8080,
}));

net.run(dstDir, { upload: true }).then(url => console.log('[*] uploaded', url));

Uploaded result can be found $ here$ .




In this example we're creating a network with a hub connected to a switch and some hosts in it. Every host has an address in format 192.168.1.X with the default mask 255.255.255.0. Everything works correct. You can view routing dump of every host node after running the animation by opening a file routing/{node-name}.routes in node's files.

Now, lets suppose we want to create a network when a Host forwards traffic from P2P connection to another Switch network. First things first, in our new script we have to set populateIP value to true (like in the above script).

const Simulator = require('net-runner-engine');
const path = require('path');


const { Network, Switch, Host, UDPClient, UDPServer } = Simulator;

const dstDir = path.resolve(__dirname, 'routing');

const net = new Network({
  animeLen: 1,
  populateIP: true,
});

const host1 = new Host(net, { name: 'UdpClient', x: 0, y: 0 });
const host2 = new Host(net, { name: 'UdpServer', x: 400, y: 0 });

host1.setupApplication(new UDPClient({
  addr: '192.168.2.1',
  port: 3000,
  onTick: ({ time, sendPacket }) => {
    if (time < 1000) {
      const buf = Buffer.from('upd-client');
      sendPacket(buf);
    }
    return '0.01s';
  },
}));

host2.setupApplication(new UDPServer({
  port: 3000,
  onReceive: ({ address, packet, reply }) => {
    console.log('[*] receive', address, packet);
    const buf = Buffer.from('udp-server');
    reply(buf);
  },
}));

const swtch = new Switch(net, { name: 'MyHomeSwitch', x: 800, y: 0 });
const tmpHosts = Array.from({ length: 3 }, (_, i) => new Host(net, { name: `Host${i}`, y: 200, x: 800 + i*200 }));

host2.connect(swtch, {
  sourceIP: '192.168.2.1',
});

tmpHosts.forEach((e, i) => {
  e.connect(swtch, {
    sourceIP: `192.168.2.${i + 2}`
  });
});

host1.connect(tmpHosts[0], {
  sourceIP: '192.168.1.1',
  targetIP: '192.168.1.2',
});

net.run(dstDir, { upload: true }).then(url => console.log('[*] uploaded', url));

Uploaded result can be found $ here$ .




Here everything works correct. We can see how host that has two connection seamlessly forward packets from UDP client to UDP server and and vice versa. However, lets try to create assign all IP addresses with mask set to 0.0.0.0. All we need to do is to add sourceMask '0.0.0.0' and targetMask: '0.0.0.0' to all necessary places in the code:

//.........
//places to add new masks

host2.connect(swtch, {
  sourceIP: '192.168.2.1',
  sourceMask: '0.0.0.0', //HERE
});

//.........

host1.connect(tmpHosts[0], {
  sourceIP: '192.168.1.1',
  targetIP: '192.168.1.2',
  sourceMask: '0.0.0.0', //HERE
  targetMask: '0.0.0.0', //HERE
});

net.run(dstDir, { upload: true }).then(url => console.log('[*] uploaded', url));

Uploaded result can be found $ here$ .

If you open the link above, you will be able to see that the UDP server is unable to reach to UDP client in order to reply with his packets and the status of his ARP request is set to delay during the whole run.




Finally, for fun we can actually turn off the populateIPoption and remove the custom IP masks and see what happens too: $ Link$  .