示例#1
0
def stop_bmx6_instances_all(remotes):
    for remote in remotes:
        exec(remote, f'pkill -SIGKILL -x bmx6 || true')
        exec(remote, f'rm -rf /tmp/bmx6-*')
示例#2
0
def stop_bmx6_instances(ids, rmap):
    for id in ids:
        remote = rmap[id]
        exec(remote, f'pkill -SIGKILL -x bmx6 --nslist ns-{id} || true')
        exec(remote, f'rm -rf /tmp/bmx6_{id}')
示例#3
0
def interface_down(remote, id, interface, ignore_error=False):
    exec(remote,
         f'ip netns exec "ns-{id}" ip link set "{interface}" down',
         ignore_error=ignore_error)
示例#4
0
def interface_flush(remote, id, interface):
    # we need to flush for IPv4 and IPv6
    exec(remote, f'ip netns exec "ns-{id}" ip -4 addr flush dev "{interface}"')
    exec(remote, f'ip netns exec "ns-{id}" ip -6 addr flush dev "{interface}"')
示例#5
0
def stop_cjdns_instances_all(remotes):
    for remote in remotes:
        exec(remote, f'pkill -SIGKILL -x cjdroute || true')
        exec(remote, f'rm -f /tmp/cjdns-*.conf')
示例#6
0
def stop_olsr2_instances(ids, rmap):
    for id in ids:
        remote = rmap[id]
        exec(remote, f'pkill -SIGKILL -x olsrd2 --nslist ns-{id} || true')
        exec(remote, f'rm -f /tmp/olsrd2-{id}.conf')
示例#7
0
def stop_olsr1_instances_all(remotes):
    for remote in remotes:
        exec(remote, f'pkill -SIGKILL -x olsrd || true')
示例#8
0
def l2tp_tunnel_exists(remote, tunnel_id):
    return int(
        exec(remote,
             f'ip l2tp show tunnel | grep -c "Tunnel {tunnel_id}" || true',
             get_output=True)[0]) != 0
示例#9
0
def stop_babel_instances_all(remotes):
    for remote in remotes:
        exec(remote, f'pkill -SIGKILL -x babeld || true')
        exec(remote, f'rm -f /tmp/babel-*.pid')
示例#10
0
def stop_babel_instances(ids, rmap):
    for id in ids:
        remote = rmap[id]
        exec(remote, f'pkill -SIGKILL -x babeld --nslist ns-{id} || true')
        exec(remote, f'rm -f /tmp/babel-{id}.pid')
示例#11
0
def stop_yggdrasil_instances(ids, rmap):
    for id in ids:
        remote = rmap[id]
        exec(remote, f'pkill -SIGKILL -x yggdrasil --nslist ns-{id} || true')
        exec(remote, f'rm -f /tmp/yggdrasil-{id}.conf')
示例#12
0
def stop_yggdrasil_instances_all(remotes):
    for remote in remotes:
        exec(remote, f'pkill -SIGKILL -x yggdrasil || true')
        exec(remote, f'rm -f /tmp/yggdrasil-*.conf')
示例#13
0
def stop_cjdns_instances(ids, rmap):
    for id in ids:
        remote = rmap[id]
        exec(remote, f'pkill -SIGKILL -x cjdroute --nslist ns-{id} || true')
        exec(remote, f'rm -f /tmp/cjdns-{id}.conf')
示例#14
0
def create_node(node, node_command=None, rmap={}):
    name = str(node['id'])
    remote = rmap.get(name)

    nsname = f'ns-{name}'
    brname = f'br-{name}'
    upname = 'uplink'
    downname = f'dl-{name}'

    exec(remote, f'ip netns add "{nsname}"')

    # up localhost
    exec(remote, f'ip netns exec "{nsname}" ip link set dev "lo" up')

    # create bridge
    exec(remote,
         f'ip netns exec "switch" ip link add name "{brname}" type bridge')
    configure_interface(remote, "switch", brname)

    # Disable spanning tree protocol (should be off by default anyway)
    exec(
        remote,
        f'ip netns exec "switch" ip link set "{brname}" type bridge stp_state 0'
    )

    # Make the bridge to act as a hub
    exec(
        remote,
        f'ip netns exec "switch" ip link set "{brname}" type bridge ageing_time 0'
    )
    exec(
        remote,
        f'ip netns exec "switch" ip link set "{brname}" type bridge forward_delay 0'
    )

    # create interface pair in switch namespace
    exec(
        remote,
        f'ip netns exec "switch" ip link add name "{upname}" type veth peer name "{downname}"'
    )

    # move uplink from namespace 'switch' into the nodes namespace
    exec(remote,
         f'ip netns exec "switch" ip link set "{upname}" netns "{nsname}"')

    # put uplinkport into bridge
    exec(remote,
         f'ip netns exec "switch" ip link set "{downname}" master "{brname}"')

    configure_interface(remote, 'switch', downname)
    configure_interface(remote, nsname, upname)

    if node_command is not None:
        exec(
            remote,
            f'ip netns exec "ns-{name}" {format_node_command(node_command, node)}'
        )
示例#15
0
def stop_olsr1_instances(ids, rmap):
    for id in ids:
        remote = rmap[id]
        exec(remote, f'pkill -SIGKILL -x olsrd --nslist ns-{id} || true')
示例#16
0
def l2tp_session_count(remote, tunnel_id):
    return int(
        exec(remote,
             f'ip l2tp show session | grep -c "tunnel {tunnel_id}" || true',
             get_output=True)[0])
示例#17
0
def stop_olsr2_instances_all(remotes):
    for remote in remotes:
        exec(remote, f'pkill -SIGKILL -x olsrd2 || true')
        exec(remote, f'rm -f /tmp/olsrd2-*.conf')
示例#18
0
def create_link(link, link_command=None, rmap={}):
    source = str(link['source'])
    target = str(link['target'])
    remote1 = rmap.get(source)
    remote2 = rmap.get(target)

    ifname1 = f've-{source}-{target}'
    ifname2 = f've-{target}-{source}'
    brname1 = f'br-{source}'
    brname2 = f'br-{target}'

    if source == target:
        eprint(
            f'Warning: Cannot create link with identical source ({source}) and target ({target}) => ignore'
        )
        return

    if remote1 == remote2:
        # create veth interface pair
        exec(
            remote1,
            f'ip netns exec "switch" ip link add "{ifname1}" type veth peer name "{ifname2}"'
        )
    else:
        # create l2tp connection
        addr1 = remote1.address
        addr2 = remote2.address

        # ids and port do not have to be the same on both remotes - but it is simpler that way
        tunnel_id = link_num(addr1, addr2, min=1, max=2**32)
        session_id = link_num(source, target, min=1, max=2**32)
        port = link_num(addr1, addr2, min=1024, max=2**16)

        if not l2tp_tunnel_exists(remote1, tunnel_id):
            exec(
                remote1,
                f'ip l2tp add tunnel tunnel_id {tunnel_id} peer_tunnel_id {tunnel_id} encap udp local {addr1} remote {addr2} udp_sport {port} udp_dport {port}'
            )
        exec(
            remote1,
            f'ip l2tp add session name {ifname1} tunnel_id {tunnel_id} session_id {session_id} peer_session_id {session_id}'
        )
        exec(remote1, f'ip link set "{ifname1}" netns "switch"')

        if not l2tp_tunnel_exists(remote2, tunnel_id):
            exec(
                remote2,
                f'ip l2tp add tunnel tunnel_id {tunnel_id} peer_tunnel_id {tunnel_id} encap udp local {addr2} remote {addr1} udp_sport {port} udp_dport {port}'
            )
        exec(
            remote2,
            f'ip l2tp add session name {ifname2} tunnel_id {tunnel_id} session_id {session_id} peer_session_id {session_id}'
        )
        exec(remote2, f'ip link set "{ifname2}" netns "switch"')

    configure_interface(remote1, 'switch', ifname1)
    configure_interface(remote2, 'switch', ifname2)

    # put into bridge
    exec(remote1,
         f'ip netns exec "switch" ip link set "{ifname1}" master "{brname1}"')
    exec(remote2,
         f'ip netns exec "switch" ip link set "{ifname2}" master "{brname2}"')

    # isolate interfaces (they can only speak to the downlink interface in the bridge they are)
    exec(
        remote1,
        f'ip netns exec "switch" bridge link set dev "{ifname1}" isolated on')
    exec(
        remote2,
        f'ip netns exec "switch" bridge link set dev "{ifname2}" isolated on')

    # e.g. execute tc command on link
    if link_command is not None:
        # source -> target
        exec(
            remote1, 'ip netns exec "switch" ' +
            format_link_command(link_command, link, 'source', ifname1))
        # target -> source
        exec(
            remote2, 'ip netns exec "switch" ' +
            format_link_command(link_command, link, 'target', ifname2))
示例#19
0
def apply(state={},
          node_command=None,
          link_command=None,
          remotes=default_remotes):
    check_access(remotes)

    new_state = state
    (cur_state, cur_state_rmap) = get_current_state(remotes)

    # handle different new_state types
    if isinstance(new_state, str):
        if new_state == 'none':
            new_state = {}
        else:
            with open(new_state) as file:
                new_state = json.load(file)

    # map each node to a remote or local computer
    # distribute evenly with minimized interconnects
    rmap = _get_remote_mapping(cur_state, new_state, remotes, cur_state_rmap)
    data = _get_task(cur_state, new_state)

    beg_ms = millis()

    # add "switch" namespace
    if state_empty(cur_state):
        for remote in remotes:
            # add switch if it does not exist yet
            exec(remote, 'ip netns add "switch" || true')
            # disable IPv6 in switch namespace (no need, less overhead)
            exec(
                remote,
                'ip netns exec "switch" sysctl -q -w net.ipv6.conf.all.disable_ipv6=1'
            )

    for node in data.nodes_update:
        update_node(node, node_command, rmap)

    for link in data.links_update:
        update_link(link, link_command, rmap)

    for node in data.nodes_create:
        create_node(node, node_command, rmap)

    for link in data.links_create:
        create_link(link, link_command, rmap)

    for link in data.links_remove:
        remove_link(link, rmap)

    for node in data.nodes_remove:
        remove_node(node, rmap)

    # remove "switch" namespace
    if state_empty(new_state):
        if verbosity == 'normal':
            print('  remove "switch"')

        for remote in remotes:
            exec(remote, 'ip netns del "switch" || true')

    # wait for tasks to complete
    wait_for_completion()
    end_ms = millis()

    if verbosity != 'quiet':
        print('Network setup in {}:'.format(format_duration(end_ms - beg_ms)))
        print(
            f'  nodes: {len(data.nodes_create)} created, {len(data.nodes_remove)} removed, {len(data.nodes_update)} updated'
        )
        print(
            f'  links: {len(data.links_create)} created, {len(data.links_remove)} removed, {len(data.links_update)} updated'
        )

    return new_state