Esempio n. 1
0
def test_all_routes():
    add_missing_methods_to_thrift()
    route_table = mkrt(ADDRESS_FAMILY_IPV4)
    # Use all_routes generator to walk empty table
    generator = route_table.all_routes()
    with pytest.raises(Exception):
        next(generator)
    # Add some routes to the table (purposely in the wrong order)
    route_table.put_route(mkr("2.2.2.0/24", N))
    route_table.put_route(mkr("1.1.1.0/24", N))
    route_table.put_route(mkr("0.0.0.0/0", S))
    route_table.put_route(mkr("1.1.1.0/24", S))
    route_table.put_route(mkr("2.2.0.0/16", S))
    # Use the generator to visit all routes
    generator = route_table.all_routes()
    rte = next(generator)
    assert rte.prefix == mkp("0.0.0.0/0")
    assert rte.owner == S
    rte = next(generator)
    assert rte.prefix == mkp("1.1.1.0/24")
    assert rte.owner == S
    rte = next(generator)
    assert rte.prefix == mkp("1.1.1.0/24")
    assert rte.owner == N
    rte = next(generator)
    assert rte.prefix == mkp("2.2.0.0/16")
    assert rte.owner == S
    rte = next(generator)
    assert rte.prefix == mkp("2.2.2.0/24")
    assert rte.owner == N
    with pytest.raises(Exception):
        next(generator)
Esempio n. 2
0
def test_ipv6_table_get_route():
    add_missing_methods_to_thrift()
    route_table = mkrt(ADDRESS_FAMILY_IPV6)
    # Try to get a route that is not present in the table (empty table)
    assert route_table.get_route(mkp("1111:1111:1111:1111:0000:0000:0000:0000/64"), S) is None
    # Try to get a route that is not present in the table (prefix is not present)
    route_table.put_route(mkr("2222:2222:2222:2222:2222:2222:2222:2222/128", S))
    assert route_table.get_route(mkp("3333:3333:3333:3333:3333:0000:0000:0000/80"), S) is None
    # Try to get a route that is not present in the table (prefix length is wrong)
    assert route_table.get_route(mkp("2222:2222:2222:2222:2222:2222:2222:0000/112"), S) is None
    # Try to get a route that is not present in the table (owner is not present)
    assert route_table.get_route(mkp("2222:2222:2222:2222:2222:2222:2222:2222/128"), N) is None
    # Get a route that is present in the table (only route for prefix)
    rte = route_table.get_route(mkp("2222:2222:2222:2222:2222:2222:2222:2222/128"), S)
    assert rte is not None
    assert rte.prefix == mkp("2222:2222:2222:2222:2222:2222:2222:2222/128")
    assert rte.owner == S
    # Add other routes to the table
    route_table.put_route(mkr("1111:1111::/32", N))
    route_table.put_route(mkr("2222:2222:2222:2222:2222:2222:2222:2222/128", N))
    route_table.put_route(mkr("2222:2222:2222::/48", N))
    route_table.put_route(mkr("3333::/16", S))
    # Get a route that is present in the table (multiple routes for prefix, get most preferred)
    rte = route_table.get_route(mkp("2222:2222:2222:2222:2222:2222:2222:2222/128"), S)
    assert rte is not None
    assert rte.prefix == mkp("2222:2222:2222:2222:2222:2222:2222:2222/128")
    assert rte.owner == S
    # Get a route that is present in the table (multiple routes for prefix, get least preferred)
    rte = route_table.get_route(mkp("2222:2222:2222:2222:2222:2222:2222:2222/128"), N)
    assert rte is not None
    assert rte.prefix == mkp("2222:2222:2222:2222:2222:2222:2222:2222/128")
    assert rte.owner == N
def test_fix_tire_packet():
    packet_common.add_missing_methods_to_thrift()
    tire_protocol_packet = encoding.ttypes.ProtocolPacket(
        header=encoding.ttypes.PacketHeader(
            major_version=packet_common.MAX_U16,
            minor_version=packet_common.MAX_U16,
            sender=packet_common.MAX_U64,
            level=packet_common.MAX_U16
        ),
        content=encoding.ttypes.PacketContent(
            lie=None,
            tide=None,
            tire=encoding.ttypes.TIREPacket(
                headers=set([
                    max_tie_header(0),
                    max_tie_header(1),
                    max_tie_header(2)
                ])
            ),
            tie=None
        )
    )
    encoded_packet = packet_common.encode_protocol_packet(tire_protocol_packet)
    decoded_tire_protocol_packet = packet_common.decode_protocol_packet(encoded_packet)
    assert tire_protocol_packet == decoded_tire_protocol_packet
Esempio n. 4
0
def test_fix_external_prefixes_tie_packet():
    packet_common.add_missing_methods_to_thrift()
    tie_protocol_packet = encoding.ttypes.ProtocolPacket(
        header=encoding.ttypes.PacketHeader(
            major_version=packet_common.MAX_U16,
            minor_version=packet_common.MAX_U16,
            sender=packet_common.MAX_U64,
            level=packet_common.MAX_U16
        ),
        content=encoding.ttypes.PacketContent(
            lie=None,
            tide=None,
            tire=None,
            tie=encoding.ttypes.TIEPacket(
                header=max_tie_header(),
                element=encoding.ttypes.TIEElement(
                    node=None,
                    prefixes=None,
                    positive_disaggregation_prefixes=None,
                    negative_disaggregation_prefixes=None,
                    external_prefixes=max_prefix_tie_element(),
                    keyvalues=None
                )
            )
        )
    )
    packet_info = packet_common.encode_protocol_packet(tie_protocol_packet, None)
    packet_info.update_env_header(0)
    packet_info.update_outer_sec_env_header(None, 111, 222, 10)
    message = b''.join(packet_info.message_parts())
    decoded_packet_info = packet_common.decode_message(None, None, message, None, None, None, None)
    assert not decoded_packet_info.error
    assert packet_info.protocol_packet == decoded_packet_info.protocol_packet
def test_fix_key_value_tie_packet():
    packet_common.add_missing_methods_to_thrift()
    tie_protocol_packet = encoding.ttypes.ProtocolPacket(
        header=encoding.ttypes.PacketHeader(
            major_version=packet_common.MAX_U16,
            minor_version=packet_common.MAX_U16,
            sender=packet_common.MAX_U64,
            level=packet_common.MAX_U16
        ),
        content=encoding.ttypes.PacketContent(
            lie=None,
            tide=None,
            tire=None,
            tie=encoding.ttypes.TIEPacket(
                header=max_tie_header(),
                element=encoding.ttypes.TIEElement(
                    node=None,
                    prefixes=None,
                    positive_disaggregation_prefixes=None,
                    negative_disaggregation_prefixes=None,
                    external_prefixes=None,
                    keyvalues=encoding.ttypes.KeyValueTIEElement(
                        keyvalues={
                            "one": "een",
                            "two": "twee"
                        }
                    )
                )
            )
        )
    )
    encoded_packet = packet_common.encode_protocol_packet(tie_protocol_packet)
    decoded_tie_protocol_packet = packet_common.decode_protocol_packet(encoded_packet)
    assert tie_protocol_packet == decoded_tie_protocol_packet
Esempio n. 6
0
def test_fix_lie_packet():
    packet_common.add_missing_methods_to_thrift()
    lie_protocol_packet = encoding.ttypes.ProtocolPacket(
        header=encoding.ttypes.PacketHeader(
            major_version=packet_common.MAX_U16,
            minor_version=packet_common.MAX_U16,
            sender=packet_common.MAX_U64,
            level=packet_common.MAX_U16),
        content=encoding.ttypes.PacketContent(lie=encoding.ttypes.LIEPacket(
            name="name",
            local_id=packet_common.MAX_U32,
            flood_port=packet_common.MAX_U16,
            link_mtu_size=packet_common.MAX_U32,
            link_bandwidth=packet_common.MAX_U32,
            neighbor=encoding.ttypes.Neighbor(originator=packet_common.MAX_U64,
                                              remote_id=packet_common.MAX_U32),
            pod=packet_common.MAX_U32,
            nonce=packet_common.MAX_U16,
            last_neighbor_nonce=packet_common.MAX_U16,
            node_capabilities=encoding.ttypes.NodeCapabilities(
                flood_reduction=True,
                hierarchy_indications=common.ttypes.HierarchyIndications.
                leaf_only),
            link_capabilities=encoding.ttypes.LinkCapabilities(bfd=False, ),
            holdtime=packet_common.MAX_U16,
            not_a_ztp_offer=True,
            you_are_flood_repeater=True,
            label=packet_common.MAX_U32),
                                              tide=None,
                                              tire=None,
                                              tie=None))
    encoded_packet = packet_common.encode_protocol_packet(lie_protocol_packet)
    decoded_lie_protocol_packet = packet_common.decode_protocol_packet(
        encoded_packet)
    assert lie_protocol_packet == decoded_lie_protocol_packet
Esempio n. 7
0
def test_ipv4_table_put_route():
    packet_common.add_missing_methods_to_thrift()
    route_table = mkrt(constants.ADDRESS_FAMILY_IPV4)
    nh1 = mknh("if1", "1.1.1.1")
    nh2 = mknh("if2", "2.2.2.2")
    assert route_table.nr_destinations() == 0
    assert route_table.nr_routes() == 0
    # Add a route
    # No next_hop
    route_table.put_route(mkr("1.1.1.0/24", N))
    assert route_table.nr_destinations() == 1
    assert route_table.nr_routes() == 1
    # Add two routes with same prefix but with different owners (most preferred added first)
    # One next_hops each
    route_table.put_route(mkr("2.2.2.2/32", S, [nh1]))
    route_table.put_route(mkr("2.2.2.2/32", N, [nh2]))
    assert route_table.nr_destinations() == 2
    assert route_table.nr_routes() == 3
    # Add two routes with same prefix but with different owners (most preferred added last)
    # Two next_hops each
    route_table.put_route(mkr("3.3.3.0/24", N, [nh1, nh2]))
    route_table.put_route(mkr("3.3.3.0/24", S, [nh1, nh2]))
    assert route_table.nr_destinations() == 3
    assert route_table.nr_routes() == 5
    # Replace route which is already in the table (only one route to prefix)
    route_table.put_route(mkr("4.4.4.0/30", N))
    route_table.put_route(mkr("4.4.4.0/30", N))
    assert route_table.nr_destinations() == 4
    assert route_table.nr_routes() == 6
    # Replace route which is already in the table (multiple routes to prefix)
    route_table.put_route(mkr("0.0.0.0/0", S))
    route_table.put_route(mkr("0.0.0.0/0", N))
    route_table.put_route(mkr("0.0.0.0/0", N))
    assert route_table.nr_destinations() == 5
    assert route_table.nr_routes() == 8
Esempio n. 8
0
def test_process_tide():
    # TODO: Also have other TIEs than prefix TIEs
    packet_common.add_missing_methods_to_thrift()
    db_tie_info_list = [
        # pylint:disable=bad-whitespace
        # Direction Origin Type     TieNr SeqNr Lifetime  Disposition
        (SOUTH, 8, PREFIX, 1, 1, 100),  # In gap before TIDE-1; start
        (SOUTH, 10, PREFIX, 1, 2, 100),  # Not in TIDE-1 (start gap); start
        (SOUTH, 10, PREFIX, 2, 5, 100),  # Not in TIDE-1 (start gap); start
        (SOUTH, 10, PREFIX, 10, 10, 100),  # Same version as in TIDE; stop
        (SOUTH, 10, PREFIX, 12, 5, 100),  # Not in TIDE-1 (middle gap); start
        (SOUTH, 10, PREFIX, 13, 3,
         100),  # Older version than in TIDE-1; request
        (NORTH, 3, PREFIX, 15, 7, 100),  # Newer version than in TIDE-1; start
        (NORTH, 4, PREFIX, 1, 1, 100),  # Not in TIDE-1 (end gap); start
        (NORTH, 10, PREFIX, 7, 6, 100),  # In TIDE-1...TIDE-2 gap; start
        (NORTH, 21, PREFIX, 15, 3,
         100),  # Older version than in TIDE-2; request
        (NORTH, 110, PREFIX, 40, 1, 100),  # In TIDE-2...TIDE-3 gap; start
        (NORTH, 210, PREFIX, 6, 6, 100)
    ]  # Not in TIDE-3 (empty); start
    test_node = make_test_node(db_tie_info_list)
    check_process_tide_1(test_node)
    check_process_tide_2(test_node)
    check_process_tide_3(test_node)
    # Test wrap-around. Finished sending all TIDEs, now send first TIDE again. The key test is
    # whether the TIE in the TIE-DB in the gap before TIDE-1 is put on the send queue again.
    check_process_tide_1(test_node)
Esempio n. 9
0
def test_ipv4_table_get_route():
    packet_common.add_missing_methods_to_thrift()
    route_table = mkrt(constants.ADDRESS_FAMILY_IPV4)
    # Try to get a route that is not present in the table (empty table)
    assert route_table.get_route(mkp("1.1.1.0/24"), S) is None
    # Try to get a route that is not present in the table (prefix is not present)
    route_table.put_route(mkr("2.2.2.0/32", S))
    assert route_table.get_route(mkp("3.3.3.0/24"), S) is None
    # Try to get a route that is not present in the table (prefix length is wrong)
    assert route_table.get_route(mkp("2.2.2.0/24"), S) is None
    # Try to get a route that is not present in the table (owner is not present)
    assert route_table.get_route(mkp("2.2.2.0/32"), N) is None
    # Get a route that is present in the table (only route for prefix)
    rte = route_table.get_route(mkp("2.2.2.0/32"), S)
    assert rte is not None
    assert rte.prefix == mkp("2.2.2.0/32")
    assert rte.owner == S
    # Add other routes to the table
    route_table.put_route(mkr("1.1.0.0/16", N))
    route_table.put_route(mkr("2.2.2.0/32", N))
    route_table.put_route(mkr("2.2.2.0/24", N))
    route_table.put_route(mkr("3.0.0.0/8", S))
    # Get a route that is present in the table (multiple routes for prefix, get most preferred)
    rte = route_table.get_route(mkp("2.2.2.0/32"), S)
    assert rte is not None
    assert rte.prefix == mkp("2.2.2.0/32")
    assert rte.owner == S
    # Get a route that is present in the table (multiple routes for prefix, get least preferred)
    rte = route_table.get_route(mkp("2.2.2.0/32"), N)
    assert rte is not None
    assert rte.prefix == mkp("2.2.2.0/32")
    assert rte.owner == N
Esempio n. 10
0
def test_cli_table():
    packet_common.add_missing_methods_to_thrift()
    route_table = mkrt(constants.ADDRESS_FAMILY_IPV4)
    nh1 = mknh("if1", "1.1.1.1")
    nh2 = mknh("if2", "2.2.2.2")
    nh3 = mknh("if3", None)
    route_table.put_route(mkr("2.2.2.0/24", N))
    route_table.put_route(mkr("1.1.1.0/24", S, [nh1]))
    route_table.put_route(mkr("0.0.0.0/0", S, [nh1, nh2]))
    route_table.put_route(mkr("2.2.0.0/16", S, [nh3]))
    route_table.put_route(mkr("1.1.1.0/24", N))
    tab_str = route_table.cli_table().to_string()
    assert (tab_str == "+------------+-----------+-------------+\n"
            "| Prefix     | Owner     | Next-hops   |\n"
            "+------------+-----------+-------------+\n"
            "| 0.0.0.0/0  | South SPF | if1 1.1.1.1 |\n"
            "|            |           | if2 2.2.2.2 |\n"
            "+------------+-----------+-------------+\n"
            "| 1.1.1.0/24 | South SPF | if1 1.1.1.1 |\n"
            "+------------+-----------+-------------+\n"
            "| 1.1.1.0/24 | North SPF |             |\n"
            "+------------+-----------+-------------+\n"
            "| 2.2.0.0/16 | South SPF | if3         |\n"
            "+------------+-----------+-------------+\n"
            "| 2.2.2.0/24 | North SPF |             |\n"
            "+------------+-----------+-------------+\n")
Esempio n. 11
0
def test_fix_tire_packet():
    packet_common.add_missing_methods_to_thrift()
    tire_protocol_packet = encoding.ttypes.ProtocolPacket(
        header=encoding.ttypes.PacketHeader(
            major_version=packet_common.MAX_U16,
            minor_version=packet_common.MAX_U16,
            sender=packet_common.MAX_U64,
            level=packet_common.MAX_U16
        ),
        content=encoding.ttypes.PacketContent(
            lie=None,
            tide=None,
            tire=encoding.ttypes.TIREPacket(
                headers=set([
                    max_tie_header_lifetime(0),
                    max_tie_header_lifetime(1),
                    max_tie_header_lifetime(2)
                ])
            ),
            tie=None
        )
    )
    packet_info = packet_common.encode_protocol_packet(tire_protocol_packet, None)
    packet_info.update_env_header(0)
    packet_info.update_outer_sec_env_header(None, 111, 222)
    message = b''.join(packet_info.message_parts())
    decoded_packet_info = packet_common.decode_message(None, None, message, None, None, None, None)
    assert not decoded_packet_info.error
    assert packet_info.protocol_packet == decoded_packet_info.protocol_packet
Esempio n. 12
0
def test_all_prefix_routes():
    packet_common.add_missing_methods_to_thrift()
    route_table = mkrt(constants.ADDRESS_FAMILY_IPV4)
    # Use all_routes generator to walk empty table
    generator = route_table.all_prefix_routes(mkp("1.2.3.4/32"))
    with pytest.raises(Exception):
        next(generator)
    # Add some routes to the table (purposely in the wrong order)
    route_table.put_route(mkr("2.2.2.0/24", N))
    route_table.put_route(mkr("1.1.1.0/24", N))
    route_table.put_route(mkr("0.0.0.0/0", S))
    route_table.put_route(mkr("1.1.1.0/24", S))
    route_table.put_route(mkr("2.2.0.0/16", S))
    # Use the generator to visit all routes for prefix 3.3.0.0/16 (there are none)
    generator = route_table.all_prefix_routes(mkp("3.3.0.0/16"))
    with pytest.raises(Exception):
        next(generator)
    # Use the generator to visit all routes for prefix 2.2.0.0/16 (there is one)
    generator = route_table.all_prefix_routes(mkp("2.2.0.0/16"))
    rte = next(generator)
    assert rte.prefix == mkp("2.2.0.0/16")
    assert rte.owner == S
    with pytest.raises(Exception):
        next(generator)
    # Use the generator to visit all routes for prefix 1.1.1.0/24 (there are two)
    generator = route_table.all_prefix_routes(mkp("1.1.1.0/24"))
    rte = next(generator)
    assert rte.prefix == mkp("1.1.1.0/24")
    assert rte.owner == S
    rte = next(generator)
    assert rte.prefix == mkp("1.1.1.0/24")
    assert rte.owner == N
    with pytest.raises(Exception):
        next(generator)
Esempio n. 13
0
def test_asserts():
    packet_common.add_missing_methods_to_thrift()
    route_table = mkrt(constants.ADDRESS_FAMILY_IPV4)
    # Passing the wrong prefix type to assert_prefix_address_family asserts
    with pytest.raises(Exception):
        packet_common.assert_prefix_address_family(
            "1.2.3.0/24", constants.ADDRESS_FAMILY_IPV4)
    with pytest.raises(Exception):
        packet_common.assert_prefix_address_family(
            mkp("1.2.3.0/24"), constants.ADDRESS_FAMILY_IPV6)
    with pytest.raises(Exception):
        packet_common.assert_prefix_address_family(
            mkp("::1.2.3.0/24"), constants.ADDRESS_FAMILY_IPV4)
    with pytest.raises(Exception):
        packet_common.assert_prefix_address_family(mkp("1.2.3.0/24"), 999)
    # Passing the wrong prefix type to the Route constructor asserts
    with pytest.raises(Exception):
        _rte = rib_route.RibRoute("1.2.3.0/24", N, [])
    # Passing the wrong prefix type to get_route asserts
    with pytest.raises(Exception):
        _rte = route_table.get_route("1.2.3.0/24", N)
    # Passing the wrong prefix type to del_route asserts
    with pytest.raises(Exception):
        _deleted = route_table.del_route("1.2.3.0/24", N)
    # The address family of the route must match the address family of the table
    with pytest.raises(Exception):
        route_table.put_route(
            mkr("1111:1111:1111:1111:0000:0000:0000:0000/64", N))
Esempio n. 14
0
def test_ipv6_table_put_route():
    add_missing_methods_to_thrift()
    route_table = mkrt(ADDRESS_FAMILY_IPV6)
    nh1 = mknh("if1", "::1.1.1.1")
    nh2 = mknh("if2", "::2.2.2.2")
    assert route_table.nr_destinations() == 0
    assert route_table.nr_routes() == 0
    # Add a route
    # No next_hop
    route_table.put_route(mkr("1111:1111:1111:1111:0000:0000:0000:0000/64", N))
    assert route_table.nr_destinations() == 1
    assert route_table.nr_routes() == 1
    # Add two routes with same prefix but with different owners (most preferred added first)
    # One next_hop each
    route_table.put_route(mkr("2222:2222:2222:2222:2222:2222:2222:2222/128", S, [nh1]))
    route_table.put_route(mkr("2222:2222:2222:2222:2222:2222:2222:2222/128", N, [nh2]))
    assert route_table.nr_destinations() == 2
    assert route_table.nr_routes() == 3
    # Add two routes with same prefix but with different owners (most preferred added last)
    # Two next_hops each
    route_table.put_route(mkr("3333:3333:3333:3333:3333:0000:0000:0000/80", N, [nh1, nh2]))
    route_table.put_route(mkr("3333:3333:3333:3333:3333:0000:0000:0000/80", S, [nh1, nh2]))
    assert route_table.nr_destinations() == 3
    assert route_table.nr_routes() == 5
    # Replace route which is already in the table (only one route to prefix)
    route_table.put_route(mkr("4444::/16", N))
    route_table.put_route(mkr("4444::/16", N))
    assert route_table.nr_destinations() == 4
    assert route_table.nr_routes() == 6
    # Replace route which is already in the table (multiple routes to prefix)
    route_table.put_route(mkr("::0.0.0.0/0", S))
    route_table.put_route(mkr("::0.0.0.0/0", N))
    route_table.put_route(mkr("::0.0.0.0/0", N))
    assert route_table.nr_destinations() == 5
    assert route_table.nr_routes() == 8
Esempio n. 15
0
def test_add_prefix_tie():
    packet_common.add_missing_methods_to_thrift()
    test_node = make_test_node()
    prefix_tie_packet_1 = packet_common.make_prefix_tie_packet(
        direction=common.ttypes.TieDirectionType.South,
        originator=222,
        tie_nr=333,
        seq_nr=444)
    timestamp = common.ttypes.IEEE802_1ASTimeStampType(AS_sec=12345)
    monotonic_clock = common.ttypes.PrefixSequenceType(timestamp=timestamp)
    packet_common.add_ipv4_prefix_to_prefix_tie(
        prefix_tie_packet_1, packet_common.make_ipv4_prefix("1.2.3.0/24"), 2,
        [77, 88], monotonic_clock)
    packet_common.add_ipv6_prefix_to_prefix_tie(
        prefix_tie_packet_1, packet_common.make_ipv6_prefix("1234:abcd::/64"),
        3)
    test_node.store_tie_packet(prefix_tie_packet_1, 555)
    prefix_tie_packet_2 = packet_common.make_prefix_tie_packet(
        direction=common.ttypes.TieDirectionType.North,
        originator=777,
        tie_nr=888,
        seq_nr=999)
    packet_common.add_ipv4_prefix_to_prefix_tie(
        prefix_tie_packet_2, packet_common.make_ipv4_prefix("0.0.0.0/0"), 10)
    test_node.store_tie_packet(prefix_tie_packet_2, 0)
    db_packet_info = test_node.find_tie_packet_info(
        prefix_tie_packet_1.header.tieid)
    db_tie_packet = db_packet_info.protocol_packet.content.tie
    assert db_tie_packet == prefix_tie_packet_1
    db_packet_info = test_node.find_tie_packet_info(
        prefix_tie_packet_2.header.tieid)
    db_tie_packet = db_packet_info.protocol_packet.content.tie
    assert db_tie_packet == prefix_tie_packet_2
    missing_tie_id = encoding.ttypes.TIEID(
        direction=common.ttypes.TieDirectionType.South,
        originator=321,
        tietype=common.ttypes.TIETypeType.PrefixTIEType,
        tie_nr=654)
    assert test_node.find_tie_packet_info(missing_tie_id) is None
    tab = test_node.tie_db_table()
    tab_str = tab.to_string()
    assert (
        tab_str ==
        "+-----------+------------+--------+--------+--------+----------+------------------------+\n"
        "| Direction | Originator | Type   | TIE Nr | Seq Nr | Lifetime | Contents               |\n"
        "+-----------+------------+--------+--------+--------+----------+------------------------+\n"
        "| South     | 222        | Prefix | 333    | 444    | 555      | Prefix: 1.2.3.0/24     |\n"
        "|           |            |        |        |        |          |   Metric: 2            |\n"
        "|           |            |        |        |        |          |   Tag: 77              |\n"
        "|           |            |        |        |        |          |   Tag: 88              |\n"
        "|           |            |        |        |        |          |   Monotonic-clock:     |\n"
        "|           |            |        |        |        |          |     Timestamp: 12345   |\n"
        "|           |            |        |        |        |          | Prefix: 1234:abcd::/64 |\n"
        "|           |            |        |        |        |          |   Metric: 3            |\n"
        "+-----------+------------+--------+--------+--------+----------+------------------------+\n"
        "| North     | 777        | Prefix | 888    | 999    | 0        | Prefix: 0.0.0.0/0      |\n"
        "|           |            |        |        |        |          |   Metric: 10           |\n"
        "+-----------+------------+--------+--------+--------+----------+------------------------+\n"
    )
Esempio n. 16
0
def test_add_prefix_tie():
    packet_common.add_missing_methods_to_thrift()
    test_node = make_test_node()
    prefix_tie_packet_1 = packet_common.make_prefix_tie_packet(
        direction=common.ttypes.TieDirectionType.South,
        originator=222,
        tie_nr=333,
        seq_nr=444,
        lifetime=555)
    packet_common.add_ipv4_prefix_to_prefix_tie(
        prefix_tie_packet_1, packet_common.make_ipv4_prefix("1.2.3.0/24"), 2,
        [77, 88], 12345)
    packet_common.add_ipv6_prefix_to_prefix_tie(
        prefix_tie_packet_1, packet_common.make_ipv6_prefix("1234:abcd::/64"),
        3)
    test_node.store_tie_packet(prefix_tie_packet_1)
    prefix_tie_packet_2 = packet_common.make_prefix_tie_packet(
        direction=common.ttypes.TieDirectionType.North,
        originator=777,
        tie_nr=888,
        seq_nr=999,
        lifetime=0)
    packet_common.add_ipv4_prefix_to_prefix_tie(
        prefix_tie_packet_2, packet_common.make_ipv4_prefix("0.0.0.0/0"), 10)
    test_node.store_tie_packet(prefix_tie_packet_2)
    assert test_node.find_tie_meta(
        prefix_tie_packet_1.header.tieid).tie_packet == prefix_tie_packet_1
    assert test_node.find_tie_meta(
        prefix_tie_packet_2.header.tieid).tie_packet == prefix_tie_packet_2
    missing_tie_id = encoding.ttypes.TIEID(
        direction=common.ttypes.TieDirectionType.South,
        originator=321,
        tietype=common.ttypes.TIETypeType.PrefixTIEType,
        tie_nr=654)
    assert test_node.find_tie_meta(missing_tie_id) is None
    tab = test_node.tie_db_table()
    tab_str = tab.to_string()
    assert (
        tab_str ==
        "+-----------+------------+--------+--------+--------+----------+--------------------------+\n"
        "| Direction | Originator | Type   | TIE Nr | Seq Nr | Lifetime | Contents                 |\n"
        "+-----------+------------+--------+--------+--------+----------+--------------------------+\n"
        "| South     | 222        | Prefix | 333    | 444    | 555      | Prefix: 1.2.3.0/24       |\n"
        "|           |            |        |        |        |          |   Metric: 2              |\n"
        "|           |            |        |        |        |          |   Tag: 77                |\n"
        "|           |            |        |        |        |          |   Tag: 88                |\n"
        "|           |            |        |        |        |          |   Monotonic-clock: 12345 |\n"
        "|           |            |        |        |        |          | Prefix: 1234:abcd::/64   |\n"
        "|           |            |        |        |        |          |   Metric: 3              |\n"
        "+-----------+------------+--------+--------+--------+----------+--------------------------+\n"
        "| North     | 777        | Prefix | 888    | 999    | 0        | Prefix: 0.0.0.0/0        |\n"
        "|           |            |        |        |        |          |   Metric: 10             |\n"
        "+-----------+------------+--------+--------+--------+----------+--------------------------+\n"
    )
Esempio n. 17
0
def test_process_tire():
    packet_common.add_missing_methods_to_thrift()
    db_tie_info_list = [
        # pylint:disable=bad-whitespace
        # Direction Origin Type     TieNr SeqNr Lifetime  Disposition
        (SOUTH, 10, PREFIX, 13, 3, 100),  # Older version than in TIRE; request
        (SOUTH, 10, PREFIX, 14, 2, 100),  # Not in TIRE; no action
        (NORTH, 3, PREFIX, 15, 7, 100),  # Newer version than in TIRE; start
        (NORTH, 4, PREFIX, 1, 8, 100)
    ]  # Same version as in TIRE; ack
    test_node = make_test_node(db_tie_info_list)
    check_process_tire(test_node)
Esempio n. 18
0
def test_ipv6_table_del_route():
    packet_common.add_missing_methods_to_thrift()
    route_table = mkrt(constants.ADDRESS_FAMILY_IPV6)
    assert route_table.nr_destinations() == 0
    assert route_table.nr_routes() == 0
    # Try to delete a route that is not present in the table (empty table)
    assert not route_table.del_route(mkp("1111:1111:1111::/48"), S)
    assert route_table.nr_destinations() == 0
    assert route_table.nr_routes() == 0
    # Try to delete a route that is not present in the table (prefix is not present)
    route_table.put_route(mkr("2222::/16", S))
    assert not route_table.del_route(
        mkp("3333:3333:3333:3333:3333:0000:0000:0000/80"), S)
    assert route_table.nr_destinations() == 1
    assert route_table.nr_routes() == 1
    # Try to delete a route that is not present in the table (prefix length is wrong)
    assert not route_table.del_route(mkp("2222:2222::/32"), S)
    assert route_table.nr_destinations() == 1
    assert route_table.nr_routes() == 1
    # Try to delete a route that is not present in the table (owner is not present)
    assert not route_table.del_route(mkp("2222::/16"), N)
    assert route_table.nr_destinations() == 1
    assert route_table.nr_routes() == 1
    # Delete a route that is present in the table (only route for prefix)
    assert route_table.get_route(mkp("2222::/16"), S) is not None
    assert route_table.del_route(mkp("2222::/16"), S)
    assert route_table.get_route(mkp("2222::/16"), S) is None
    assert route_table.nr_destinations() == 0
    assert route_table.nr_routes() == 0
    # Put the deleted route back and add other routes to the table
    route_table.put_route(mkr("::/0", N))
    route_table.put_route(mkr("2222::/16", N))
    route_table.put_route(mkr("2222::/16", S))
    route_table.put_route(mkr("2222:2222::/32", N))
    route_table.put_route(mkr("3333:3333:3333:3333:3333:0000:0000:0000/80", S))
    route_table.put_route(mkr("3333:3333:3333:3333:3333:3333:3333:3333/128",
                              S))
    assert route_table.nr_destinations() == 5
    assert route_table.nr_routes() == 6
    # Delete a route that is present in the table (multiple routes for prefix, get most preferred)
    assert route_table.get_route(mkp("2222::/16"), S) is not None
    assert route_table.del_route(mkp("2222::/16"), S)
    assert route_table.get_route(mkp("2222::/16"), S) is None
    assert route_table.nr_destinations() == 5
    assert route_table.nr_routes() == 5
    route_table.put_route(mkr("2222::/16", S))
    # Delete a route that is present in the table (multiple routes for prefix, get least preferred)
    assert route_table.get_route(mkp("2222::/16"), N) is not None
    assert route_table.del_route(mkp("2222::/16"), N)
    assert route_table.get_route(mkp("2222::/16"), N) is None
    assert route_table.nr_destinations() == 5
    assert route_table.nr_routes() == 5
    route_table.put_route(mkr("2222::/16", N))
Esempio n. 19
0
def main():
    args = parse_command_line_arguments()
    parse_environment_variables(args)
    parsed_config = config.parse_configuration(args.configfile)
    packet_common.add_missing_methods_to_thrift()
    eng = engine.Engine(run_which_nodes=run_which_nodes(args),
                        passive_nodes=args.passive_nodes,
                        interactive=args.interactive,
                        telnet_port_file=args.telnet_port_file,
                        multicast_loopback=multicast_loopback(args),
                        log_level=args.log_level,
                        config=parsed_config)
    eng.run()
Esempio n. 20
0
def test_ipv4_table_del_route():
    packet_common.add_missing_methods_to_thrift()
    route_table = mkrt(constants.ADDRESS_FAMILY_IPV4)
    assert route_table.nr_destinations() == 0
    assert route_table.nr_routes() == 0
    # Try to delete a route that is not present in the table (empty table)
    assert not route_table.del_route(mkp("1.1.1.0/24"), S)
    assert route_table.nr_destinations() == 0
    assert route_table.nr_routes() == 0
    # Try to delete a route that is not present in the table (prefix is not present)
    route_table.put_route(mkr("2.2.2.0/32", S))
    assert not route_table.del_route(mkp("3.3.3.0/24"), S)
    assert route_table.nr_destinations() == 1
    assert route_table.nr_routes() == 1
    # Try to delete a route that is not present in the table (prefix length is wrong)
    assert not route_table.del_route(mkp("2.2.2.0/24"), S)
    assert route_table.nr_destinations() == 1
    assert route_table.nr_routes() == 1
    # Try to delete a route that is not present in the table (owner is not present)
    assert not route_table.del_route(mkp("2.2.2.0/32"), N)
    assert route_table.nr_destinations() == 1
    assert route_table.nr_routes() == 1
    # Delete a route that is present in the table (only route for prefix)
    assert route_table.get_route(mkp("2.2.2.0/32"), S) is not None
    assert route_table.del_route(mkp("2.2.2.0/32"), S)
    assert route_table.get_route(mkp("2.2.2.0/32"), S) is None
    assert route_table.nr_destinations() == 0
    assert route_table.nr_routes() == 0
    # Put the deleted route back and add other routes to the table
    route_table.put_route(mkr("1.1.0.0/16", N))
    route_table.put_route(mkr("2.2.2.0/32", S))
    route_table.put_route(mkr("2.2.2.0/32", N))
    route_table.put_route(mkr("2.2.2.0/24", N))
    route_table.put_route(mkr("3.0.0.0/8", S))
    assert route_table.nr_destinations() == 4
    assert route_table.nr_routes() == 5
    # Delete a route that is present in the table (multiple routes for prefix, get most preferred)
    assert route_table.get_route(mkp("2.2.2.0/32"), S) is not None
    assert route_table.del_route(mkp("2.2.2.0/32"), S)
    assert route_table.get_route(mkp("2.2.2.0/32"), S) is None
    assert route_table.nr_destinations() == 4
    assert route_table.nr_routes() == 4
    route_table.put_route(mkr("2.2.2.0/32", S))
    # Delete a route that is present in the table (multiple routes for prefix, get least preferred)
    assert route_table.get_route(mkp("2.2.2.0/32"), N) is not None
    assert route_table.del_route(mkp("2.2.2.0/32"), N)
    assert route_table.get_route(mkp("2.2.2.0/32"), N) is None
    assert route_table.nr_destinations() == 4
    assert route_table.nr_routes() == 4
    route_table.put_route(mkr("2.2.2.0/32", N))
Esempio n. 21
0
def test_fix_node_tie_packet():
    packet_common.add_missing_methods_to_thrift()
    tie_protocol_packet = encoding.ttypes.ProtocolPacket(
        header=encoding.ttypes.PacketHeader(
            major_version=packet_common.MAX_U16,
            minor_version=packet_common.MAX_U16,
            sender=packet_common.MAX_U64,
            level=packet_common.MAX_U16
        ),
        content=encoding.ttypes.PacketContent(
            lie=None,
            tide=None,
            tire=None,
            tie=encoding.ttypes.TIEPacket(
                header=max_tie_header(),
                element=encoding.ttypes.TIEElement(
                    node=encoding.ttypes.NodeTIEElement(
                        level=packet_common.MAX_U16,
                        neighbors={
                            max_system_id(0): max_neighbor(),
                            max_system_id(1): max_neighbor(),
                            max_system_id(2): max_neighbor()
                        },
                        capabilities=encoding.ttypes.NodeCapabilities(
                            protocol_minor_version=protocol_minor_version,
                            flood_reduction=True,
                            hierarchy_indications=common.ttypes.HierarchyIndications.leaf_only
                        ),
                        flags=encoding.ttypes.NodeFlags(
                            overload=True
                        ),
                        name="name"
                    ),
                    prefixes=None,
                    positive_disaggregation_prefixes=None,
                    negative_disaggregation_prefixes=None,
                    external_prefixes=None,
                    keyvalues=None
                )
            )
        )
    )
    packet_info = packet_common.encode_protocol_packet(tie_protocol_packet, None)
    packet_info.update_env_header(0)
    packet_info.update_outer_sec_env_header(None, 111, 222, 10)
    message = b''.join(packet_info.message_parts())
    decoded_packet_info = packet_common.decode_message(None, None, message, None, None, None, None)
    assert not decoded_packet_info.error
    assert packet_info.protocol_packet == decoded_packet_info.protocol_packet
Esempio n. 22
0
def test_process_tie():
    packet_common.add_missing_methods_to_thrift()
    db_tie_info_list = [
        # pylint:disable=bad-whitespace
        # Direction Origin         Type     TieNr SeqNr Lifetime  Disposition
        (SOUTH, 12, NODE, 3, 2, 600),  # TIE_NEWER
        (SOUTH, 10, PREFIX, 13, 5, 100),  # TIE_NEWER
        (SOUTH, MY_SYSTEM_ID, NODE, 1, 8, 150),  # My real node TIE
        (SOUTH, MY_SYSTEM_ID, PREFIX, 1, 4, 69),  # TIE_OLDER_SELF
        (NORTH, 5, PREFIX, 3, 2, 200),  # TIE_OLDER
        (NORTH, 5, PREFIX, 8, 12, 100),  # TIE_SAME
        (NORTH, 6, PREFIX, 7, 4, 500)
    ]  # TIE_SAME
    test_node = make_test_node(db_tie_info_list)
    check_process_tie(test_node)
Esempio n. 23
0
def test_fix_lie_packet():
    packet_common.add_missing_methods_to_thrift()
    lie_protocol_packet = encoding.ttypes.ProtocolPacket(
        header=encoding.ttypes.PacketHeader(
            major_version=packet_common.MAX_U16,
            minor_version=packet_common.MAX_U16,
            sender=packet_common.MAX_U64,
            level=packet_common.MAX_U16
        ),
        content=encoding.ttypes.PacketContent(
            lie=encoding.ttypes.LIEPacket(
                name="name",
                local_id=packet_common.MAX_U32,
                flood_port=packet_common.MAX_U16,
                link_mtu_size=packet_common.MAX_U32,
                link_bandwidth=packet_common.MAX_U32,
                neighbor=encoding.ttypes.Neighbor(
                    originator=packet_common.MAX_U64,
                    remote_id=packet_common.MAX_U32
                ),
                pod=packet_common.MAX_U32,
                # nonce=packet_common.MAX_U16,
                # last_neighbor_nonce=packet_common.MAX_U16,
                node_capabilities=encoding.ttypes.NodeCapabilities(
                    protocol_minor_version=protocol_minor_version,
                    flood_reduction=True,
                    hierarchy_indications=common.ttypes.HierarchyIndications.leaf_only
                ),
                link_capabilities=encoding.ttypes.LinkCapabilities(
                    bfd=False,
                ),
                holdtime=packet_common.MAX_U16,
                not_a_ztp_offer=True,
                you_are_flood_repeater=True,
                label=packet_common.MAX_U32
            ),
            tide=None,
            tire=None,
            tie=None
        )
    )
    packet_info = packet_common.encode_protocol_packet(lie_protocol_packet, None)
    packet_info.update_env_header(0)
    packet_info.update_outer_sec_env_header(None, 111, 222)
    message = b''.join(packet_info.message_parts())
    decoded_packet_info = packet_common.decode_message(None, None, message, None, None, None, None)
    assert not decoded_packet_info.error
    assert packet_info.protocol_packet == decoded_packet_info.protocol_packet
Esempio n. 24
0
def test_fix_node_tie_packet():
    packet_common.add_missing_methods_to_thrift()
    tie_protocol_packet = encoding.ttypes.ProtocolPacket(
        header=encoding.ttypes.PacketHeader(
            major_version=packet_common.MAX_U16,
            minor_version=packet_common.MAX_U16,
            sender=packet_common.MAX_U64,
            level=packet_common.MAX_U16
        ),
        content=encoding.ttypes.PacketContent(
            lie=None,
            tide=None,
            tire=None,
            tie=encoding.ttypes.TIEPacket(
                header=max_tie_header(),
                element=encoding.ttypes.TIEElement(
                    node=encoding.ttypes.NodeTIEElement(
                        level=packet_common.MAX_U16,
                        neighbors={
                            max_system_id(0): max_neighbor(),
                            max_system_id(1): max_neighbor(),
                            max_system_id(2): max_neighbor()
                        },
                        capabilities=encoding.ttypes.NodeCapabilities(
                            flood_reduction=True,
                            hierarchy_indications=common.ttypes.HierarchyIndications.leaf_only
                        ),
                        flags=encoding.ttypes.NodeFlags(
                            overload=True
                        ),
                        name="name"
                    ),
                    prefixes=None,
                    positive_disaggregation_prefixes=None,
                    negative_disaggregation_prefixes=None,
                    external_prefixes=None,
                    keyvalues=None
                )
            )
        )
    )
    encoded_packet = packet_common.encode_protocol_packet(tie_protocol_packet)
    decoded_tie_protocol_packet = packet_common.decode_protocol_packet(encoded_packet)
    assert tie_protocol_packet == decoded_tie_protocol_packet
Esempio n. 25
0
def test_age_ties():
    packet_common.add_missing_methods_to_thrift()
    db_tie_info_list = [
        # pylint:disable=bad-whitespace
        # Direction Origin         Type     TieNr SeqNr Lifetime
        (SOUTH, 55, NODE, 2, 4, 600),
        (SOUTH, MY_SYSTEM_ID, PREFIX, 18, 903, 1)
    ]
    test_node = make_test_node(db_tie_info_list)
    tie_id_1 = packet_common.make_tie_id(SOUTH, 55, NODE, 2)
    tie_id_2 = packet_common.make_tie_id(SOUTH, MY_SYSTEM_ID, PREFIX, 18)
    assert test_node.find_tie_packet_info(tie_id_1) is not None
    assert test_node.find_tie_packet_info(tie_id_2) is not None
    test_node.age_ties()
    tie_packet_info_1 = test_node.find_tie_packet_info(tie_id_1)
    assert tie_packet_info_1 is not None
    assert tie_packet_info_1.protocol_packet.content.tie.header.seq_nr == 4
    assert tie_packet_info_1.remaining_tie_lifetime == 599
    assert test_node.find_tie_packet_info(tie_id_2) is None
Esempio n. 26
0
def test_cli_routes_table():
    packet_common.add_missing_methods_to_thrift()
    kern = kernel.Kernel(log=None, log_id="", table_name="main")
    if not kern.platform_supported:
        return
    # We assume that the main route table always has a default route, and we look for this:
    # +-------------+---------+--------------------+-------------+-----------+-----------+------------+--------+
    # | Table       | Address | Destination        | Type        | Protocol  | Outgoing  | Gateway    | Weight |
    # |             | Family  |                    |             |           | Interface |            |        |
    # +-------------+---------+--------------------+-------------+-----------+-----------+------------+--------+
    # ...
    # | Main        | IPv4    | 0.0.0.0/0          | Unicast     | Boot/Dhcp | eth0      | 172.17.0.1 |        |
    # ...
    tab_str = kern.cli_routes_table(254).to_string()
    pattern = (r"[|] Table +[|] Address +[|] Destination +[|] Type +[|] Protocol +[|] Outgoing +[|] Gateway +[|] Weight +[|]\n"
               r"[|] +[|] Family +[|] +[|] +[|] +[|] Interface +[|] +[|] +[|]\n"
               r"(.|[\n])*"
               r"[|] Main +[|] IPv4 +[|] 0\.0\.0\.0/0 +[|] Unicast +[|]")
    assert re.search(pattern, tab_str) is not None
Esempio n. 27
0
def test_mark_and_del_stale():
    packet_common.add_missing_methods_to_thrift()
    route_table = mkrt(constants.ADDRESS_FAMILY_IPV4)
    # Mark all S routes stale on an empty table
    assert route_table.mark_owner_routes_stale(S) == 0
    # Delete all remaining stale routes (which there are none)
    assert route_table.del_stale_routes() == 0
    # Prepare a route table with a mixture of N and S routes
    route_table.put_route(mkr("0.0.0.0/0", S))
    route_table.put_route(mkr("1.1.1.0/24", S))
    route_table.put_route(mkr("1.1.1.0/24", N))
    route_table.put_route(mkr("2.2.0.0/16", S))
    route_table.put_route(mkr("2.2.2.0/24", N))
    # Mark all N routes stale
    assert route_table.mark_owner_routes_stale(N) == 2
    # Overwrite an existing routes that was marked stale
    route_table.put_route(mkr("1.1.1.0/24", N))
    # Overwrite an existing routes that was not marked stale
    route_table.put_route(mkr("2.2.0.0/16", S))
    # Add a new route
    route_table.put_route(mkr("3.3.0.0/16", N))
    # Delete the one remaining stale route
    assert route_table.del_stale_routes() == 1
Esempio n. 28
0
def test_generate_tide_packet():
    packet_common.add_missing_methods_to_thrift()
    db_tie_info_list = [
        # pylint:disable=bad-whitespace
        # Direction Origin         Type     TieNr SeqNr Lifetime  Allowed in TIDE
        (SOUTH, 55, PREFIX, 2, 4, 600
         ),  # No : Non-node S-TIE to S, not self-originated
        (SOUTH, MY_SYSTEM_ID, PREFIX, 18, 903, 400)
    ]  # Yes: Non-node S-TIE to S, self-originated
    test_node = make_test_node(db_tie_info_list)
    tide_packet = test_node.generate_tide_packet(
        neighbor_direction=SOUTH,
        neighbor_system_id=55,
        neighbor_level=8,
        neighbor_is_top_of_fabric=False,
        my_level=MY_LEVEL,
        i_am_top_of_fabric=True)
    assert tide_packet.start_range == node.Node.MIN_TIE_ID
    assert tide_packet.end_range == node.Node.MAX_TIE_ID
    assert len(tide_packet.headers) == 1
    expected_header = packet_common.make_tie_header_with_lifetime(
        SOUTH, MY_SYSTEM_ID, PREFIX, 18, 903, 400)
    assert tide_packet.headers[0] == expected_header
Esempio n. 29
0
import re

# pylint: disable=W0401
# pylint: disable=W0614
from common.ttypes import *
from encoding.ttypes import *
import packet_common

packet_common.add_missing_methods_to_thrift()


# TODO: Remove this horrible hack.
# This is a horrible hack to work around the following problem. I am having huge problems getting
# my visualization tool to properly correlate sent message to received messages (i.e. to properly
# draw the lines from the sender to the receiver). As Tony has pointed out several times, Thrift
# encoding is not canonical. On top of that, even for the exact same binary message, two different
# Python processes may create different internal binary structures because Python dictionaries use
# non-deterministic hashes (this is by design - it is a security feature). The following code works
# around the problem: it converts a ProtocolPacket object into another object (nested tuples) which
# consistently hash to the same value, regardless of the order in which iterators visit member of
# dictionary or set. It does this by sorting non-deterministic containers and converting them to
# tuples. I have proposed adding a correlator field the transport header to solve the problem more
# fundamentally; if and when that happens we can remove this hack, and the need for packet decoding,
# and we can move the visualization tool back to the tools directory.
#
def make_deterministic_hashable(obj, top=True):
    # This function produces the same has for objects that contain dictionaries and that only differ
    # in the order in which the dict iterators visit the members of the dict.
    if not top:
        try:
            hash(obj)
Esempio n. 30
0
def test_is_flood_allowed():
    packet_common.add_missing_methods_to_thrift()
    test_node = make_test_node()
    # Node 66 is same level as me
    node_66_tie_packet = packet_common.make_node_tie_packet(name="node66",
                                                            level=MY_LEVEL,
                                                            direction=SOUTH,
                                                            originator=66,
                                                            tie_nr=5,
                                                            seq_nr=7)
    test_node.store_tie_packet(node_66_tie_packet, 300)
    # Node 77 has higher level than me
    node_77_tie_packet = packet_common.make_node_tie_packet(name="node77",
                                                            level=MY_LEVEL + 1,
                                                            direction=SOUTH,
                                                            originator=77,
                                                            tie_nr=3,
                                                            seq_nr=2)
    test_node.store_tie_packet(node_77_tie_packet, 400)
    # Node 88 has lower level than me
    node_88_tie_packet = packet_common.make_node_tie_packet(name="node88",
                                                            level=MY_LEVEL - 1,
                                                            direction=SOUTH,
                                                            originator=88,
                                                            tie_nr=7,
                                                            seq_nr=3)
    test_node.store_tie_packet(node_88_tie_packet, 400)
    tx_tie_info_list = [
        # pylint:disable=bad-whitespace
        #                                                              Neighbor   Neighbor   I am    Allowed  Reason
        # Direction  Originator     Type,    Tie-Nr  Seq-Nr  Lifetime  Direction  System-ID  ToF
        (SOUTH, 66, NODE, 5, 7, 400, SOUTH, 22, False, True,
         "Node S-TIE to S: originator level is same as from-node"),
        (SOUTH, 77, NODE, 3, 2, 300, SOUTH, 18, False, False,
         "Node S-TIE to S: originator level is not same as from-node"),
        (SOUTH, 55, NODE, 8, 12, 500, NORTH, 17, False, False,
         "Node S-TIE to N: could not determine originator level"),
        (SOUTH, 77, NODE, 3, 3, 200, NORTH, 17, True, True,
         "Node S-TIE to N: originator level is higher than from-node"),
        (SOUTH, 88, NODE, 7, 3, 400, NORTH, 19, False, False,
         "Node S-TIE to N: originator level is not higher than from-node"),
        (SOUTH, 55, NODE, 8, 12, 550, EW, 19, True, False,
         "Node S-TIE to EW: from-node is top of fabric"),
        (SOUTH, 55, NODE, 8, 12, 550, EW, 19, False, True,
         "Node S-TIE to EW: from-node is not top of fabric"),
        (SOUTH, 55, NODE, 8, 12, 550, None, 19, False, False,
         "Node S-TIE to ?: never flood"),
        (SOUTH, MY_SYSTEM_ID, PREFIX, 4, 7, 200, SOUTH, 20, False, True,
         "Non-node S-TIE to S: self-originated"),
        (SOUTH, 55, PREFIX, 2, 4, 600, SOUTH, 20, True, False,
         "Non-node S-TIE to S: not self-originated"),
        (SOUTH, MY_SYSTEM_ID, PREFIX, 18, 903, 400, SOUTH, 33, True, True,
         "Non-node S-TIE to S: self-originated"),
        (SOUTH, 55, PREFIX, 2, 4, 600, NORTH, 55, False, True,
         "Non-node S-TIE to N: to-node is originator of TIE"),
        (SOUTH, 55, PREFIX, 2, 4, 600, NORTH, 33, False, False,
         "Non-node S-TIE to N: to-node is not originator of TIE"),
        (SOUTH, 55, PREFIX, 2, 4, 600, EW, 33, True, False,
         "Non-node S-TIE to EW: this top of fabric"),
        (SOUTH, MY_SYSTEM_ID, PREFIX, 18, 903, 400, EW, 33, False, True,
         "Non-node S-TIE to EW: self-originated and not top of fabric"),
        (SOUTH, 55, PREFIX, 2, 4, 600, EW, 33, False, False,
         "Non-node S-TIE to EW: not self-originated"),
        (SOUTH, 55, PREFIX, 2, 4, 600, None, 33, True, False,
         "None-node S-TIE to ?: never flood"),
        (NORTH, 55, NODE, 3, 3, 500, SOUTH, 20, False, False,
         "N-TIE to S: never flood"),
        (NORTH, 55, PREFIX, 2, 4, 500, SOUTH, 20, True, False,
         "N-TIE to S: never flood"),
        (NORTH, 55, NODE, 3, 3, 500, NORTH, 20, False, True,
         "N-TIE to N: always flood"),
        (NORTH, 55, PREFIX, 2, 4, 500, NORTH, 20, True, True,
         "N-TIE to N: always flood"),
        (NORTH, 55, NODE, 3, 3, 500, EW, 20, True, True,
         "N-TIE to EW: top of fabric"),
        (NORTH, 55, NODE, 3, 3, 500, EW, 20, False, False,
         "N-TIE to EW: not top of fabric"),
        (NORTH, 55, NODE, 3, 3, 500, None, 20, False, False,
         "N-TIE to ?: never flood")
    ]
    for tx_tie_info in tx_tie_info_list:
        (direction, originator, tietype, tie_nr, seq_nr, lifetime,
         neighbor_direction, neighbor_system_id, i_am_top_of_fabric,
         expected_allowed, expected_reason) = tx_tie_info
        tie_header = packet_common.make_tie_header_with_lifetime(
            direction, originator, tietype, tie_nr, seq_nr, lifetime)
        (allowed, reason) = test_node.is_flood_allowed(
            tie_header=tie_header.header,
            to_node_direction=neighbor_direction,
            to_node_system_id=neighbor_system_id,
            from_node_system_id=MY_SYSTEM_ID,
            from_node_level=MY_LEVEL,
            from_node_is_top_of_fabric=i_am_top_of_fabric)
        assert allowed == expected_allowed, expected_reason
        assert reason == expected_reason