def get_anns(self):
        c1 = Community("100:16")
        c2 = Community("100:17")
        c3 = Community("100:18")

        ann1 = Announcement(prefix='Prefix1',
                            peer='Peer1',
                            origin=BGP_ATTRS_ORIGIN.EBGP,
                            as_path=[1, 2, 5, 7, 6],
                            as_path_len=5,
                            next_hop='Hop1',
                            local_pref=100,
                            med=10,
                            communities={
                                c1: True,
                                c2: False,
                                c3: False
                            },
                            permitted=True)

        ann2 = Announcement(prefix='Prefix2',
                            peer='Peer2',
                            origin=BGP_ATTRS_ORIGIN.EBGP,
                            as_path=[9, 2, 5, 7, 8],
                            as_path_len=VALUENOTSET,
                            next_hop='Hop2',
                            local_pref=VALUENOTSET,
                            med=10,
                            communities={
                                c1: False,
                                c2: False,
                                c3: VALUENOTSET
                            },
                            permitted=True)
        return ann1, ann2
Esempio n. 2
0
    def get_anns(self, prefix):
        c1 = Community("100:16")
        c2 = Community("100:17")
        c3 = Community("100:18")

        ann1 = Announcement(
            prefix=prefix, peer='R1', origin=BGP_ATTRS_ORIGIN.EBGP,
            as_path=[100], as_path_len=1,
            next_hop='Hop1', local_pref=100, med=10,
            communities={c1: True, c2: False, c3: False}, permitted=True)
        return [ann1]
Esempio n. 3
0
 def get_announcements(self, num_anns, num_communities):
     # Communities
     all_communities = [
         Community("100:%d" % i) for i in range(num_communities)
     ]
     cs = dict([(c, False) for c in all_communities])
     anns = {}
     for i in range(num_anns):
         ann = Announcement(prefix='P_%s' % i,
                            peer='ATT',
                            origin=BGP_ATTRS_ORIGIN.EBGP,
                            as_path=[1, 2, 5, 7, 6],
                            as_path_len=5,
                            next_hop='ATTHop',
                            local_pref=100,
                            communities=cs,
                            permitted=True)
         anns["%s_%s" % (ann.peer, ann.prefix)] = ann
     return anns
Esempio n. 4
0
def two_ebgp_nodes(export_path):
    """
    Two routers connected via eBGP
    Very simple once router announces a single prefix and the other selects it
    """
    graph = NetworkGraph()
    r1, r2 = 'R1', 'R2'
    graph.add_router(r1)
    graph.add_router(r2)
    graph.add_router_edge(r1, r2)
    graph.add_router_edge(r2, r1)

    # BGP configs
    graph.set_bgp_asnum(r1, 100)
    graph.set_bgp_asnum(r2, 200)
    # Establish peering
    # The actual network interfaces used for peering will be synthesized
    graph.add_bgp_neighbor(r1,
                           r2,
                           router_a_iface=VALUENOTSET,
                           router_b_iface=VALUENOTSET)

    # Some internal network
    net = ip_network(u'128.0.0.0/24')
    prefix = '128_0_0_0'
    prefix_map = {prefix: net}
    lo0 = 'lo0'
    graph.set_loopback_addr(
        r1, lo0, ip_interface("%s/%d" % (net.hosts().next(), net.prefixlen)))
    # Announce the internal network
    graph.add_bgp_announces(r1, lo0)

    # The communities recognized by us
    comms = [Community("100:10"), Community("100:20")]

    # The announcement that will be propagated by R1
    ann = Announcement(prefix=prefix,
                       peer=r1,
                       origin=BGP_ATTRS_ORIGIN.EBGP,
                       next_hop='R1Hop',
                       as_path=[100],
                       as_path_len=1,
                       local_pref=100,
                       med=100,
                       communities=dict([(c, False) for c in comms]),
                       permitted=True)

    path = PathReq(Protocols.BGP, prefix, ['R2', 'R1'], False)
    reqs = [path]

    # Get SMT Context
    ctx = create_context(reqs, graph, [ann])

    propagation = EBGPPropagation(reqs, graph, ctx)

    propagation.compute_dags()
    propagation.synthesize()

    # Synthesize all the interfaces and link configurations
    connecte_syn = ConnectedSyn([], graph, full=True)
    connecte_syn.synthesize()

    # SMT Solving
    solver = z3.Solver(ctx=ctx.z3_ctx)
    assert ctx.check(solver) == z3.sat, solver.unsat_core()

    # Update graph with the concrete values after solver
    propagation.update_network_graph()
    gns3 = GNS3Topo(graph=graph, prefix_map=prefix_map)
    gns3.write_configs('%s/ibgp-simple' % export_path)
Esempio n. 5
0
def test_double_import():
    """Unit test of Route maps"""
    graph = NetworkGraph()
    r1, r2 = 'R1', 'R2'
    graph.add_router(r1)
    graph.add_router(r2)
    graph.add_router_edge(r1, r2)
    graph.add_router_edge(r2, r1)

    # BGP configs
    graph.set_bgp_asnum(r1, 100)
    graph.set_bgp_asnum(r2, 200)
    # Establish peering
    # The actual network interfaces used for peering will be synthesized
    graph.add_bgp_neighbor(r1,
                           r2,
                           router_a_iface=VALUENOTSET,
                           router_b_iface=VALUENOTSET)

    # Some internal network
    net = ip_network(u'128.0.0.0/24')
    prefix = '128_0_0_0'
    prefix_map = {prefix: net}
    lo0 = 'lo0'
    graph.set_loopback_addr(
        r1, lo0, ip_interface("%s/%d" % (net.hosts().next(), net.prefixlen)))
    # Announce the internal network
    graph.add_bgp_announces(r1, lo0)

    # The communities recognized by us
    comms = [Community("100:10"), Community("100:20")]

    # The announcement that will be propagated by R1
    ann = Announcement(prefix=prefix,
                       peer=r1,
                       origin=BGP_ATTRS_ORIGIN.EBGP,
                       next_hop='R1Hop',
                       as_path=[100],
                       as_path_len=1,
                       local_pref=100,
                       med=100,
                       communities=dict([(c, False) for c in comms]),
                       permitted=True)

    path = PathReq(Protocols.BGP, prefix, ['R2', 'R1'], False)
    reqs = [path]

    ctx = create_context(reqs, graph, [ann], create_as_paths=True)

    from synet.utils.fnfree_policy import SMTRouteMap
    rline1 = RouteMapLine(matches=None,
                          actions=None,
                          access=VALUENOTSET,
                          lineno=10)
    deny_line1 = RouteMapLine(matches=None,
                              actions=None,
                              access=Access.deny,
                              lineno=100)
    rmap1 = RouteMap(name='Rmap1', lines=[rline1, deny_line1])
    rline2 = RouteMapLine(matches=None,
                          actions=None,
                          access=VALUENOTSET,
                          lineno=10)
    deny_line2 = RouteMapLine(matches=None,
                              actions=None,
                              access=Access.deny,
                              lineno=100)
    rmap2 = RouteMap(name='Rmap1', lines=[rline2, deny_line2])
    sym = get_sym([ann], ctx)

    smt1 = SMTRouteMap(rmap1, sym, ctx)
    smt2 = SMTRouteMap(rmap2, smt1.announcements, ctx)
    print "Original permitted", sym.announcements[0].permitted
    print "SMT 1 permitted", smt1.announcements[0].permitted
    print "SMT 2 permitted", smt2.announcements[0].permitted
    ctx.register_constraint(smt1.announcements[0].permitted.var == True)
    ctx.register_constraint(smt2.announcements[0].permitted.var == False)
    solver = z3.Solver(ctx=ctx.z3_ctx)
    ret = ctx.check(solver)
    #print solver.to_smt2()
    assert ret == z3.sat, solver.unsat_core()
    #print solver.model()
    print "Original permitted", sym.announcements[0].permitted
    print "SMT 1 permitted", smt1.announcements[0].permitted
    print "SMT 2 permitted", smt2.announcements[0].permitted
Esempio n. 6
0
def linear_ebgp(N, export_path):
    """
    Routers connected in a line and each eBGP pair with it's direct neighbors
    """
    # Topology
    g = get_ebgp_linear_topo(N)
    # Announce locally
    prefix = "Prefix0"
    net = ip_network(u'128.0.0.0/24')
    prefix_map = {prefix: net}
    g.set_loopback_addr(
        'R1', 'lo0',
        ip_interface("%s/%d" % (net.hosts().next(), net.prefixlen)))
    g.add_bgp_announces('R1', 'lo0')

    # Announcement
    comms = [Community("100:10"), Community("100:20")]
    cs = dict([(c, False) for c in comms])
    # The announcement that will be propagated by R1
    ann = get_announcement(prefix=prefix, peer='R1', comms=cs)

    # Set up route maps
    for i in range(1, N + 1):
        first = 'R%d' % (i - 1) if i > 1 else None
        middle = 'R%d' % i
        last = 'R%d' % (i + 1) if i < N else None
        if last:
            matches = [MatchAsPath(VALUENOTSET)]
            #matches = None
            rline = RouteMapLine(matches, None, VALUENOTSET, 10)
            deny_line = RouteMapLine(None, None, Access.deny, 100)
            rmap = RouteMap('Exp_%s' % last, [rline, deny_line])
            g.add_route_map(middle, rmap)
            g.add_bgp_export_route_map(middle, last, rmap.name)
        if first:
            matches = [MatchAsPath(VALUENOTSET)]
            #matches = None
            rline = RouteMapLine(matches, None, VALUENOTSET, 10)
            deny_line = RouteMapLine(None, None, Access.deny, 100)
            rmap = RouteMap('Imp_%s' % first, [rline, deny_line])
            g.add_route_map(middle, rmap)
            g.add_bgp_import_route_map(middle, first, rmap.name)

    # nx.nx_pydot.write_dot(g, '/tmp/linear.xdot')
    req = PathReq(Protocols.BGP,
                  dst_net='Prefix0',
                  path=['R2', 'R1'],
                  strict=False)

    ctx = create_context([req], g, [ann])

    propagation = EBGPPropagation([req], g, ctx)
    propagation.compute_dags()
    propagation.synthesize()

    solver = z3.Solver(ctx=ctx.z3_ctx)
    ret = ctx.check(solver)
    assert ret == z3.sat, solver.unsat_core()
    propagation.update_network_graph()

    gns3 = GNS3Topo(g, prefix_map)
    gns3.write_configs('%s/linear-ebgp-%d' % (export_path, N))
Esempio n. 7
0
def two_ebgp_nodes_route_map(export_path):
    """
    Two routers connected via eBGP with route maps
    Very simple one router announces a single prefix and the other selects it
    """
    graph = NetworkGraph()
    r1, r2 = 'R1', 'R2'
    graph.add_router(r1)
    graph.add_router(r2)
    graph.add_router_edge(r1, r2)
    graph.add_router_edge(r2, r1)

    # BGP configs
    graph.set_bgp_asnum(r1, 100)
    graph.set_bgp_asnum(r2, 200)
    # Establish peering
    # The actual network interfaces used for peering will be synthesized
    graph.add_bgp_neighbor(r1,
                           r2,
                           router_a_iface=VALUENOTSET,
                           router_b_iface=VALUENOTSET)

    # Some internal network
    net = ip_network(u'128.0.0.0/24')
    prefix = '128_0_0_0'
    prefix_map = {prefix: net}
    lo0 = 'lo0'
    graph.set_loopback_addr(
        r1, lo0, ip_interface("%s/%d" % (net.hosts().next(), net.prefixlen)))
    # Announce the internal network
    graph.add_bgp_announces(r1, lo0)

    # The communities recognized by us
    comms = [Community("100:10"), Community("100:20")]

    # The announcement that will be propagated by R1
    ann = Announcement(prefix=prefix,
                       peer=r1,
                       origin=BGP_ATTRS_ORIGIN.EBGP,
                       next_hop='R1Hop',
                       as_path=[100],
                       as_path_len=1,
                       local_pref=100,
                       med=100,
                       communities=dict([(c, False) for c in comms]),
                       permitted=True)

    path = PathReq(Protocols.BGP, prefix, ['R2', 'R1'], False)
    reqs = [path]

    # Create a route map to export from R1 to R2
    iplist = IpPrefixList(name='IpList1',
                          access=Access.permit,
                          networks=[prefix])
    graph.add_ip_prefix_list(r1, iplist)
    ip_match = MatchIpPrefixListList(iplist)
    set_community = ActionSetCommunity([comms[0]])
    rline = RouteMapLine(matches=[ip_match],
                         actions=[set_community],
                         access=Access.permit,
                         lineno=10)
    export_map = RouteMap(name="Export_R1_to_R2", lines=[rline])
    # Register the route map
    graph.add_route_map(r1, export_map)
    # Set the route map as an export route map
    graph.add_bgp_export_route_map(r1, r2, export_map.name)

    # Create a route map to import at R2 to from R1
    comm_list = CommunityList(list_id=1,
                              access=Access.permit,
                              communities=[comms[0]])
    graph.add_bgp_community_list(r2, comm_list)
    comm_match = MatchCommunitiesList(comm_list)
    set_local_pref = ActionSetLocalPref(200)
    rline = RouteMapLine(matches=[MatchNextHop(VALUENOTSET)],
                         actions=[set_local_pref],
                         access=Access.permit,
                         lineno=10)
    import_map = RouteMap(name="Import_R2_from_R1", lines=[rline])
    # Register the route map
    graph.add_route_map(r2, import_map)
    # Set the route map as an import route map
    graph.add_bgp_import_route_map(r2, r1, import_map.name)

    # Get SMT Context
    ctx = create_context(reqs, graph, [ann])
    propagation = EBGPPropagation(reqs, graph, ctx)
    propagation.compute_dags()
    propagation.synthesize()

    # Synthesize all the interfaces and link configurations
    connecte_syn = ConnectedSyn([], graph, full=True)
    connecte_syn.synthesize()

    # SMT Solving
    solver = z3.Solver(ctx=ctx.z3_ctx)
    assert ctx.check(solver) == z3.sat, solver.unsat_core()

    # Update graph with the concrete values after solver
    propagation.update_network_graph()
    gns3 = GNS3Topo(graph=graph, prefix_map=prefix_map)
    gns3.write_configs('%s/ebgp-route-map' % export_path)
    graph.write_graphml('%s/ebgp-route-map/topology.graphml' % export_path)
Esempio n. 8
0
    def get_cust_peer_linear_topo(self):
        graph = gen_mesh(2, 100)
        r1, r2 = 'R1', 'R2'

        graph.enable_ospf(r1)
        graph.enable_ospf(r2)
        graph.add_ospf_network(r1, 'Fa0/0', '0.0.0.0')

        # Add two providers and one customer
        provider1 = 'Provider1'
        provider2 = 'Provider2'
        customer = 'Customer'
        graph.add_peer(provider1)
        graph.add_peer(provider2)
        graph.add_peer(customer)
        graph.set_bgp_asnum(provider1, 400)
        graph.set_bgp_asnum(provider2, 500)
        graph.set_bgp_asnum(customer, 600)
        graph.add_peer_edge(r1, provider1)
        graph.add_peer_edge(provider1, r1)
        graph.add_peer_edge(r1, provider2)
        graph.add_peer_edge(provider2, r1)
        graph.add_peer_edge(r2, customer)
        graph.add_peer_edge(customer, r2)

        # Establish BGP peering
        graph.add_bgp_neighbor(provider1, r1)
        graph.add_bgp_neighbor(provider2, r1)
        graph.add_bgp_neighbor(customer, r2)

        net1 = ip_network(u'128.0.0.0/24')
        net2 = ip_network(u'128.0.1.0/24')
        prefix1 = str(net1)
        prefix2 = str(net2)
        iface_addr1 = ip_interface("%s/%d" % (net1.hosts().next(), net1.prefixlen))
        graph.set_loopback_addr(provider1, 'lo10', iface_addr1)
        graph.set_loopback_addr(provider2, 'lo10', iface_addr1)
        iface_addr2 = ip_interface("%s/%d" % (net2.hosts().next(), net2.prefixlen))
        graph.set_loopback_addr(customer, 'lo10', iface_addr2)
        # Announce IGP internally
        graph.add_ospf_network(r1, 'lo100', area='0.0.0.0')
        graph.add_ospf_network(r2, 'lo100', area='0.0.0.0')

        # Known communities
        comms = [Community("100:{}".format(c)) for c in range(1, 4)]
        # The symbolic announcement injected by provider1
        ann1 = Announcement(prefix1,
                            peer=provider1,
                            origin=BGP_ATTRS_ORIGIN.INCOMPLETE,
                            as_path=[1000, 2000, 5000],  # We assume it learned from other upstream ASes
                            as_path_len=3,
                            next_hop='{}Hop'.format(provider1),
                            local_pref=100,
                            med=100,
                            communities=dict([(c, False) for c in comms]),
                            permitted=True)
        # The symbolic announcement injected by provider1
        # Note it has a shorter AS Path
        ann2 = Announcement(str(prefix1),
                            peer=provider2,
                            origin=BGP_ATTRS_ORIGIN.INCOMPLETE,
                            as_path=[3000, 600, 9000, 5000],  # We assume it learned from other upstream ASes
                            as_path_len=4,
                            next_hop='{}Hop'.format(provider2),
                            local_pref=100,
                            med=100,
                            communities=dict([(c, False) for c in comms]),
                            permitted=True)

        # The symbolic announcement injected by customer
        ann3 = Announcement(prefix2,
                            peer=customer,
                            origin=BGP_ATTRS_ORIGIN.INCOMPLETE,
                            as_path=[],
                            as_path_len=0,
                            next_hop='{}Hop'.format(customer),
                            local_pref=100,
                            med=100,
                            communities=dict([(c, False) for c in comms]),
                            permitted=True)

        return graph, [ann1, ann2, ann3]
Esempio n. 9
0
def bgp_example(output_dir):
    # Generate the basic network of three routers
    graph = gen_mesh(3, 100)
    r1, r2, r3, r4 = 'R1', 'R2', 'R3', 'R4'

    # Enable OSPF in the sketch
    for node in graph.local_routers_iter():
        graph.enable_ospf(node, 100)
    # Edge weights are symbolic
    for src, dst in graph.edges():
        graph.set_edge_ospf_cost(src, dst, VALUENOTSET)
    graph.set_loopback_addr(r3, 'lo100', VALUENOTSET)
    graph.set_loopback_addr(r2, 'lo100', VALUENOTSET)
    graph.add_ospf_network(r1, 'lo100', '0.0.0.0')
    graph.add_ospf_network(r2, 'lo100', '0.0.0.0')
    graph.add_ospf_network(r3, 'lo100', '0.0.0.0')
    graph.add_ospf_network(r1, 'Fa0/0', '0.0.0.0')
    graph.add_ospf_network(r2, 'Fa0/0', '0.0.0.0')
    graph.add_ospf_network(r3, 'Fa0/0', '0.0.0.0')

    # Add two providers and one customer
    provider1 = 'Provider1'
    provider2 = 'Provider2'
    customer = 'Customer'
    graph.add_peer(provider1)
    graph.add_peer(provider2)
    graph.add_peer(customer)
    graph.set_bgp_asnum(provider1, 400)
    graph.set_bgp_asnum(provider2, 500)
    graph.set_bgp_asnum(customer, 600)
    graph.add_peer_edge(r2, provider1)
    graph.add_peer_edge(provider1, r2)
    graph.add_peer_edge(r3, provider2)
    graph.add_peer_edge(provider2, r3)
    graph.add_peer_edge(r1, customer)
    graph.add_peer_edge(customer, r1)

    # Establish BGP peering
    graph.add_bgp_neighbor(provider1, r2)
    graph.add_bgp_neighbor(provider2, r3)
    graph.add_bgp_neighbor(customer, r1)

    # The traffic class announced by the two providers
    net1 = ip_network(u'128.0.0.0/24')
    # The traffic class announced by the customer
    net2 = ip_network(u'128.0.1.0/24')

    prefix1 = str(net1)
    prefix2 = str(net2)
    # Known communities
    comms = [Community("100:{}".format(c)) for c in range(1, 4)]
    # The symbolic announcement injected by provider1
    ann1 = Announcement(
        prefix1,
        peer=provider1,
        origin=BGP_ATTRS_ORIGIN.INCOMPLETE,
        as_path=[5000],  # We assume it learned from other upstream ASes
        as_path_len=1,
        #next_hop='0.0.0.0',
        next_hop='{}Hop'.format(provider1),
        local_pref=100,
        med=100,
        communities=dict([(c, False) for c in comms]),
        permitted=True)
    # The symbolic announcement injected by provider1
    # Note it has a shorter AS Path
    ann2 = Announcement(
        prefix1,
        peer=provider2,
        origin=BGP_ATTRS_ORIGIN.INCOMPLETE,
        as_path=[3000, 5000],  # We assume it learned from other upstream ASes
        as_path_len=2,
        next_hop='0.0.0.0',
        local_pref=100,
        med=100,
        communities=dict([(c, False) for c in comms]),
        permitted=True)
    # The symbolic announcement injected by customer
    ann3 = Announcement(prefix2,
                        peer=customer,
                        origin=BGP_ATTRS_ORIGIN.INCOMPLETE,
                        as_path=[],
                        as_path_len=0,
                        next_hop='0.0.0.0',
                        local_pref=100,
                        med=100,
                        communities=dict([(c, False) for c in comms]),
                        permitted=True)

    graph.add_bgp_advertise(provider1, ann1, loopback='lo100')
    graph.set_loopback_addr(provider1, 'lo100',
                            ip_interface(net1.hosts().next()))

    graph.add_bgp_advertise(provider2, ann2, loopback='lo100')
    graph.set_loopback_addr(provider2, 'lo100',
                            ip_interface(net1.hosts().next()))

    graph.add_bgp_advertise(customer, ann3, loopback='lo100')
    graph.set_loopback_addr(customer, 'lo100',
                            ip_interface(net2.hosts().next()))

    ########################## Configuration sketch ###############################

    for local, peer in [(r2, provider1), (r3, provider2)]:
        imp_name = "{}_import_from_{}".format(local, peer)
        exp_name = "{}_export_to_{}".format(local, peer)
        imp = RouteMap.generate_symbolic(name=imp_name,
                                         graph=graph,
                                         router=local)
        exp = RouteMap.generate_symbolic(name=exp_name,
                                         graph=graph,
                                         router=local)
        graph.add_bgp_import_route_map(local, peer, imp.name)
        graph.add_bgp_export_route_map(local, peer, exp.name)

    for local, peer in [(r2, r3), (r3, r2)]:
        # In Cisco the last line is a drop by default
        rline1 = RouteMapLine(matches=[],
                              actions=[],
                              access=VALUENOTSET,
                              lineno=10)
        from tekton.bgp import Access
        rline2 = RouteMapLine(matches=[],
                              actions=[],
                              access=Access.deny,
                              lineno=100)
        rmap_export = RouteMap(name='{}_export_{}'.format(local, peer),
                               lines=[rline1, rline2])
        graph.add_route_map(local, rmap_export)
        graph.add_bgp_export_route_map(local, peer, rmap_export.name)

    # Requirements
    path1 = PathReq(Protocols.BGP, prefix1, [customer, r1, r2, provider1],
                    False)
    path2 = PathReq(Protocols.BGP, prefix1, [customer, r1, r3, r2, provider1],
                    False)
    path3 = PathReq(Protocols.BGP, prefix1, [r3, r1, r2, provider1], False)

    path4 = PathReq(Protocols.BGP, prefix1, [customer, r1, r3, provider2],
                    False)
    path5 = PathReq(Protocols.BGP, prefix1, [customer, r1, r2, r3, provider2],
                    False)
    path6 = PathReq(Protocols.BGP, prefix1, [r2, r1, r3, provider2], False)

    reqs = [
        PathOrderReq(Protocols.BGP, prefix1, [
            KConnectedPathsReq(Protocols.BGP, prefix1, [path1, path2, path3],
                               False),
            KConnectedPathsReq(Protocols.BGP, prefix1, [path4, path5, path6],
                               False),
        ], False),
        PathOrderReq(Protocols.OSPF, "dummy", [
            PathReq(Protocols.OSPF, "dummy", [r1, r2], False),
            PathReq(Protocols.OSPF, "dummy", [r1, r3, r2], False),
        ], False),
        PathOrderReq(Protocols.OSPF, "dummy", [
            PathReq(Protocols.OSPF, "dummy", [r1, r3], False),
            PathReq(Protocols.OSPF, "dummy", [r1, r2, r3], False),
        ], False),
    ]
    external_anns = [ann1, ann2, ann3]
    netcomplete = NetComplete(reqs=reqs,
                              topo=graph,
                              external_announcements=external_anns)
    netcomplete.synthesize()
    netcomplete.write_configs(output_dir=output_dir)
Esempio n. 10
0
def bgp(n, nreqs=10):
    req_file = './topos/cav/gridrand%d-bgp-%d-req.logic' % (n, nreqs)
    topo = gen_grid_topology(n, n, 0)
    static_reqs, ospf_reqs, bgp_reqs = read_reqs(req_file)

    seed = 159734782
    path_gen = 200
    ospfRand = random.Random(seed)

    for node in topo.routers_iter():
        topo.enable_ospf(node, 100)
        topo.set_bgp_asnum(node, 100)
        # Initially all costs are empty
        topo.set_static_routes_empty(node)

    for src, dst in topo.edges():
        topo.set_edge_ospf_cost(src, dst, VALUENOTSET)

    peer = 'ATT'
    egresses = set([p.path[-2] for p in bgp_reqs])
    topo.add_peer(peer)
    topo.set_bgp_asnum(peer, 5000)
    for req in bgp_reqs:
        req.path.append(peer)

    for egress in egresses:
        topo.add_peer_edge(peer, egress)
        topo.add_peer_edge(egress, peer)
        topo.add_bgp_neighbor(peer, egress, VALUENOTSET, VALUENOTSET)

    for src in topo.local_routers_iter():
        for dst in topo.local_routers_iter():
            if src == dst or dst in topo.get_bgp_neighbors(src):
                continue
            topo.add_bgp_neighbor(src, dst, VALUENOTSET, VALUENOTSET)

    prefix = 'GOOGLE'
    communities = [Community("100:%d" % i) for i in range(5)]
    ann = Announcement(prefix=prefix,
                       peer=peer,
                       origin=BGP_ATTRS_ORIGIN.EBGP,
                       as_path=[1, 2, 5000],
                       as_path_len=3,
                       next_hop='%sHop' % peer,
                       local_pref=100,
                       med=10,
                       communities=dict([(c, False) for c in communities]),
                       permitted=True)
    topo.add_bgp_advertise(peer, ann)

    conn = ConnectedSyn([], topo, full=True)
    conn.synthesize()

    static_syn = StaticSyn(static_reqs, topo)
    static_syn.synthesize()

    ospf = OSPFCEGIS(topo, gen_paths=path_gen, random_obj=ospfRand)
    for req in ospf_reqs:
        ospf.add_req(req)

    assert ospf.synthesize(allow_ecmp=True)
    assert not ospf.removed_reqs

    for router in topo.local_routers_iter():
        count = itertools.count(1)
        for neighbor in topo.get_bgp_neighbors(router):
            if router == neighbor:
                continue
            comm_list = CommunityList(
                list_id=count.next(),
                access=Access.permit,
                communities=[VALUENOTSET, VALUENOTSET, VALUENOTSET])
            topo.add_bgp_community_list(router, comm_list)
            match_comm = MatchCommunitiesList(comm_list)
            iplist = IpPrefixList(name='ip%s' % count.next(),
                                  access=Access.permit,
                                  networks=[VALUENOTSET])
            topo.add_ip_prefix_list(router, iplist)
            match_ip = MatchIpPrefixListList(iplist)
            match_next_hop = MatchNextHop(VALUENOTSET)
            match_sel = MatchSelectOne([match_comm, match_next_hop, match_ip])
            actions = [
                ActionSetLocalPref(VALUENOTSET),
                ActionSetCommunity([VALUENOTSET], True)
            ]
            rline = RouteMapLine([match_sel], actions, VALUENOTSET, 10)
            dline = RouteMapLine(None, None, Access.deny, 100)
            rmap = RouteMap("Rimp_%s_from_%s" % (router, neighbor),
                            lines=[rline, dline])
            topo.add_route_map(router, rmap)
            topo.add_bgp_import_route_map(router, neighbor, rmap.name)

    ctx = create_context(bgp_reqs, topo, [ann])
    p = EBGPPropagation(bgp_reqs, topo, ctx)
    p.compute_dags()
    p.synthesize()
    solver = z3.Solver()
    ret = ctx.check(solver)
    assert ret == z3.sat, solver.unsat_core()
    p.update_network_graph()