Skip to content
Snippets Groups Projects
network.py 2.35 KiB
Newer Older
Jarrod Pas's avatar
Jarrod Pas committed
from itertools import combinations

import networkx as nx

Jarrod Pas's avatar
Jarrod Pas committed
from .packet import PacketGenerator
from .node import NodeFactory
Jarrod Pas's avatar
Jarrod Pas committed
from .routers import types as routers
from .traces import types as traces
Jarrod Pas's avatar
Jarrod Pas committed

class Network:
    ''''''
    def __init__(self, env,
                 packets=None,
                 node_factory=None,
                 community=None,
                 trace=None):
        ''''''
        self.env = env

        # contact trace
        if trace is None:
            trace = traces['random']()
        self.trace = trace
Jarrod Pas's avatar
Jarrod Pas committed
        self.trace.start(env, network=self)
Jarrod Pas's avatar
Jarrod Pas committed

        # community detection
        self.community = community
        if community is not None:
Jarrod Pas's avatar
Jarrod Pas committed
            self.community.start(env, network=self)
Jarrod Pas's avatar
Jarrod Pas committed

        # packet generation
        if packets is None:
Jarrod Pas's avatar
Jarrod Pas committed
            packets = {}
        self.packets = PacketGenerator(**packets)
Jarrod Pas's avatar
Jarrod Pas committed
        self.packets.start(env, network=self)
Jarrod Pas's avatar
Jarrod Pas committed

        # create node network
        if node_factory is None:
            node_factory = NodeFactory(tick_rate=1, router=routers['direct'])
        self.nodes = [
            node_factory(self, nid)
Jarrod Pas's avatar
Jarrod Pas committed
            for nid in range(self.trace.nodes)
        ]
        self.links = [
            (a, b)
            for a, b in combinations(self.nodes, 2)
        ]

        # set up networkx graph
        self.graph = nx.Graph()
        self.graph.add_nodes_from(self.nodes)
        self.graph.add_edges_from([
            (a, b, { 'state': False })
            for a, b in self.links
        ])

    def set_link(self, a, b, state):
        if isinstance(a, int):
            a = self.nodes[a]

        if isinstance(b, int):
            b = self.nodes[b]

        edge = self[a][b]
        if edge['state'] == state:
            return

        if state is None:
            state = not edge['state']
        edge['state'] = state

        if self.community:
            self.community.set_link(a, b, state, self.env.now)

        if state:
            a.route_packets()
            b.route_packets()

Jarrod Pas's avatar
Jarrod Pas committed
    def toggle_link(self, a, b):
        self.set_link(a, b, None)

    def send_link(self, a, b, packet):
        ''''''
Jarrod Pas's avatar
Jarrod Pas committed
        if self.graph[a][b]['state']:
Jarrod Pas's avatar
Jarrod Pas committed
            # TODO: transfer delay
            b.recv(packet)
        else:
            raise Exception('Nodes {} and {} not connected'.format(a, b))

    def __getitem__(self, node):
        ''''''
        return self.graph[node]