def test_ordered_notvalid(self): fan_out = 4 network_graph = self.get_triangles(fan_out) source = 'source' sink = 'sink' p1 = [source, 'R1', sink] p2 = [source, 'R2', sink] p3 = [source, 'R3', sink] path1 = PathReq(Protocols.OSPF, 'Google', p1, False) path2 = PathReq(Protocols.OSPF, 'Google', p2, False) path3 = PathReq(Protocols.OSPF, 'Google', p3, False) paths = [path1, path2, path3] order_req1 = PathOrderReq(Protocols.OSPF, 'Google', paths, False) order_req2 = PathOrderReq(Protocols.OSPF, 'Google', [path3, path2, path1], False) ospf = synet.synthesis.ospf_heuristic.OSPFSyn(network_graph, gen_paths=10) ospf.add_req(order_req1) ospf.add_req(order_req2) ret = ospf.synthesize() self.assertFalse(ret)
def generate_ordered_reqs(topo, reqsize, ordered, rand): """Generate reqsize of PathOrderReq each has ordered paths""" graph = nx.DiGraph() for src, dst in topo.edges(): graph.add_edge(src, dst) computed_paths = {} tmp_cost = 'tmp-cost' for src, dst in graph.edges(): graph[src][dst][tmp_cost] = rand.randint(1, sys.maxint) for src in graph.nodes(): for dst in graph.nodes(): if src == dst: continue if (src, dst) not in computed_paths: shortest = nx.shortest_path(graph, src, dst, weight=tmp_cost) computed_paths[(src, dst)] = [shortest] edges = list(graph.edges()) for src, dst in edges: cost = graph[src][dst][tmp_cost] graph.remove_edge(src, dst) if nx.has_path(graph, src, dst): shortest = nx.shortest_path(graph, src, dst, weight=tmp_cost) if shortest not in computed_paths[(src, dst)]: computed_paths[(src, dst)].append(shortest) graph.add_edge(src, dst, **{tmp_cost: cost}) valid = [] for (src, dst) in computed_paths: k = len(computed_paths[(src, dst)]) if k == ordered: valid.append(computed_paths[(src, dst)]) if len(valid) >= reqsize: sampled = random.sample(valid, reqsize) reqs = [] for plist in sampled: req = PathOrderReq(Protocols.OSPF, plist[0][-1], [ PathReq(Protocols.OSPF, path[-1], path, False) for path in plist ], False) reqs.append(req) return reqs else: print "Regenerating random ordered paths" return generate_ordered_reqs(topo, reqsize, ordered, rand)
def test_ordered_correct(self): fan_out = 4 network_graph = self.get_triangles(fan_out) source = 'source' sink = 'sink' p1 = [source, 'R1', sink] p2 = [source, 'R2', sink] p3 = [source, 'R3', sink] p4 = [source, 'R4', sink] path1 = PathReq(Protocols.OSPF, 'Google', p1, False) path2 = PathReq(Protocols.OSPF, 'Google', p2, False) path3 = PathReq(Protocols.OSPF, 'Google', p3, False) paths = [path1, path2, path3] order_req = PathOrderReq(Protocols.OSPF, 'Google', paths, False) ospf = synet.synthesis.ospf_heuristic.OSPFSyn(network_graph, gen_paths=10) ospf.add_req(order_req) ret = ospf.synthesize() self.assertTrue(ret) ospf.update_network_graph() p1_cost = [ network_graph.get_edge_ospf_cost(src, dst) for src, dst in zip(p1[0::1], p1[1::1]) ] p2_cost = [ network_graph.get_edge_ospf_cost(src, dst) for src, dst in zip(p2[0::1], p2[1::1]) ] p3_cost = [ network_graph.get_edge_ospf_cost(src, dst) for src, dst in zip(p3[0::1], p3[1::1]) ] p4_cost = [ network_graph.get_edge_ospf_cost(src, dst) for src, dst in zip(p4[0::1], p4[1::1]) ] p1_cost = sum(p1_cost) p2_cost = sum(p2_cost) p3_cost = sum(p3_cost) p4_cost = sum(p4_cost) self.assertLessEqual(p1_cost, p2_cost) self.assertLessEqual(p2_cost, p3_cost) self.assertLessEqual(p3_cost, p4_cost)
def test_expand(self): # Arrange g = get_griffin_ibgp_graph() p0 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R2_2', 'R2_0', 'R4', 'R1'], strict=False) p1 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R2_2', 'R1'], strict=False) r2_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p0, p1], strict=False) p2 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R3', 'R2_3', 'R1'], strict=False) p3 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R3', 'R1'], strict=False) r3_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p2, p3], strict=False) r4_req = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R4', 'R1'], strict=False) p6 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R5_3', 'R5_2', 'R5_0', 'R4', 'R1'], strict=False) p7 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R5_3', 'R5_1', 'R3', 'R1'], strict=False) r5_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p6, p7], strict=False) reqs = [r2_req, r3_req, r4_req, r5_req] ctx = self.create_context(reqs, g) propagation = EBGPPropagation(reqs, g, ctx) # Act # Case 1: Direct eBGP p1 = propagation.expand_as_path((100, ), ['R1']) p2 = propagation.expand_as_path((100, 400), ['R1']) self.assertEquals(p1, set([ ('R1', ), ])) self.assertEquals(p2, set([('R1', 'R4')])) # Case 2: Direct eBGP->iBGP p3 = propagation.expand_as_path((100, 200), ['R1']) paths_to_r2 = set([ ('R1', 'R2_2'), ('R1', 'R2_2', 'R2_0'), ('R1', 'R2_2', 'R2_1'), ('R1', 'R2_2', 'R2_3'), ('R1', 'R2_3'), ('R1', 'R2_3', 'R2_0'), ('R1', 'R2_3', 'R2_1'), ('R1', 'R2_3', 'R2_2'), ]) self.assertEquals(p3, paths_to_r2) ## Case 3: eBGP-> iBGP -> eBGP p4 = propagation.expand_as_path((100, 200, 300), ['R1']) paths_to_r3 = set([ ('R1', 'R2_2', 'R2_1', 'R3'), ('R1', 'R2_2', 'R2_3', 'R3'), ('R1', 'R2_3', 'R3'), ('R1', 'R2_3', 'R2_1', 'R3'), ]) self.assertEquals(p4, paths_to_r3)
def test_good_gadget_ibgp(self): # Arrange g = get_griffin_ibgp_graph() for src in g.routers_iter(): for dst in g.get_bgp_neighbors(src): if src == dst: continue # Export matches1 = [MatchAsPath(VALUENOTSET)] matches2 = [MatchAsPath(VALUENOTSET)] rline1 = RouteMapLine(matches1, [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 10) rline2 = RouteMapLine(matches2, [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 20) rmap = RouteMap('Exp_%s' % dst, [rline1, rline2]) g.add_route_map(src, rmap) g.add_bgp_export_route_map(src, dst, rmap.name) # Import matches1 = [MatchAsPath(VALUENOTSET)] matches2 = [MatchAsPath(VALUENOTSET)] rline1 = RouteMapLine(matches1, [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 10) rline2 = RouteMapLine(matches2, [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 20) rmap = RouteMap('Imp_%s' % dst, [rline1, rline2]) g.add_route_map(src, rmap) g.add_bgp_import_route_map(src, dst, rmap.name) p0 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R2_2', 'R2_0', 'R4', 'R1'], strict=False) p1 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R2_2', 'R1'], strict=False) r2_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p0, p1], strict=False) p2 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R3', 'R2_3', 'R1'], strict=False) p3 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R3', 'R1'], strict=False) r3_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p2, p3], strict=False) r4_req = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R4', 'R1'], strict=False) p6 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R5_3', 'R5_2', 'R5_0', 'R4', 'R1'], strict=False) p7 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R5_3', 'R5_1', 'R3', 'R1'], strict=False) r5_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p6, p7], strict=False) reqs = [r2_req, r3_req, r4_req, r5_req] ctx = self.create_context(reqs, g) # Act propagation = EBGPPropagation(reqs, g, ctx) unmatching_order = propagation.compute_dags() ebgp = propagation.ebgp_graphs['Prefix0'] ibgp = propagation.ibgp_graphs['Prefix0'] #nx.nx_pydot.write_dot(ibgp, '/tmp/ibgp_good.xdot') #nx.nx_pydot.write_dot(ebgp, '/tmp/ebgp_good.xdot') # Assert assert not unmatching_order # Assert eBGP propagation self.assertEqual(ebgp.node[100]['order'], [set([(100, )])]) self.assertEqual( ebgp.node[200]['order'], [set([(100, 400, 200)]), set([(100, 200)])]) self.assertEqual( ebgp.node[300]['order'], [set([(100, 200, 300)]), set([(100, 300)])]) self.assertEqual(ebgp.node[400]['order'], [set([(100, 400)])]) self.assertEqual(ebgp.node[500]['order'], [set([(100, 400, 500)]), set([(100, 300, 500)])]) # Assert iBGP propagation self.assertEqual(ibgp.node['R1']['order'], [set([('R1', )])]) self.assertEqual(ibgp.node['R2_0']['order'], [set([('R1', 'R4', 'R2_0')])]) self.assertEqual(ibgp.node['R2_1']['order'], []) self.assertEqual( ibgp.node['R2_2']['order'], [set([('R1', 'R4', 'R2_0', 'R2_2')]), set([('R1', 'R2_2')])]) self.assertEqual(ibgp.node['R2_3']['order'], [set([('R1', 'R2_3')])]) self.assertEqual(ibgp.node['R3']['order'], [set([('R1', 'R2_3', 'R3')]), set([('R1', 'R3')])]) self.assertEqual(ibgp.node['R4']['order'], [set([('R1', 'R4')])]) self.assertEqual(ibgp.node['R5_0']['order'], [set([('R1', 'R4', 'R5_0')])]) self.assertEqual(ibgp.node['R5_1']['order'], [set([('R1', 'R3', 'R5_1')])]) self.assertEqual(ibgp.node['R5_2']['order'], [set([('R1', 'R4', 'R5_0', 'R5_2')])]) self.assertEqual(ibgp.node['R5_3']['order'], [ set([('R1', 'R4', 'R5_0', 'R5_2', 'R5_3')]), set([('R1', 'R3', 'R5_1', 'R5_3')]) ]) propagation.synthesize()
def test_bad_gadget(self): # Arrange g = get_griffin_graph() p0 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R2', 'R4', 'R1'], strict=False) p1 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R2', 'R1'], strict=False) r2_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p0, p1], strict=False) p2 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R3', 'R2', 'R1'], strict=False) p3 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R3', 'R1'], strict=False) r3_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p2, p3], strict=False) p4 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R4', 'R5', 'R3', 'R1'], strict=False) p5 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R4', 'R1'], strict=False) r4_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p4, p5], strict=False) p6 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R5', 'R3', 'R1'], strict=False) p7 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R5', 'R4', 'R1'], strict=False) r5_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p6, p7], strict=False) reqs = [r2_req, r3_req, r4_req, r5_req] # Action ctx = self.create_context(reqs, g) propagation = EBGPPropagation(reqs, g, ctx) unmatching_order = propagation.compute_dags() dag = propagation.ebgp_graphs['Prefix0'] # Assert assert unmatching_order
def test_good_gadget(self): # Arrange g = get_griffin_graph() net = "Prefix0" prefix_map = {net: ip_network(u'128.0.0.0/24')} addr = (prefix_map[net].hosts().next(), prefix_map[net].prefixlen) g.set_loopback_addr('R1', 'lo0', ip_interface("%s/%d" % addr)) for src in g.routers_iter(): for dst in g.get_bgp_neighbors(src): if src == dst: continue # Export ip_list = IpPrefixList(name="L_%s-to_%s" % (src, dst), access=Access.permit, networks=[VALUENOTSET]) g.add_ip_prefix_list(src, ip_list) rline = RouteMapLine([MatchIpPrefixListList(ip_list)], [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 10) rmap = RouteMap('Exp_%s' % dst, [rline]) g.add_route_map(src, rmap) g.add_bgp_export_route_map(src, dst, rmap.name) # Import #rline = RouteMapLine(None, [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 10) #rmap = RouteMap('Imp_%s' % dst, [rline]) #g.add_route_map(src, rmap) #g.add_bgp_import_route_map(src, dst, rmap.name) rline1 = RouteMapLine([MatchAsPath(VALUENOTSET)], [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 10) rline2 = RouteMapLine([MatchAsPath(VALUENOTSET)], [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 20) rline3 = RouteMapLine([MatchAsPath(VALUENOTSET)], [ActionSetLocalPref(VALUENOTSET)], VALUENOTSET, 30) rmap = RouteMap('Imp_%s' % dst, [rline1, rline2, rline3]) g.add_route_map(src, rmap) g.add_bgp_import_route_map(src, dst, rmap.name) p0 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R2', 'R4', 'R1'], strict=False) p1 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R2', 'R1'], strict=False) r2_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p0, p1], strict=False) p2 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R3', 'R2', 'R1'], strict=False) p3 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R3', 'R1'], strict=False) r3_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p2, p3], strict=False) r4_req = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R4', 'R1'], strict=False) p6 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R5', 'R4', 'R1'], strict=False) p7 = PathReq(Protocols.BGP, dst_net='Prefix0', path=['R5', 'R3', 'R1'], strict=False) r5_req = PathOrderReq(Protocols.BGP, dst_net='Prefix0', paths=[p6, p7], strict=False) # Action reqs = [r2_req, r3_req, r4_req, r5_req] ctx = self.create_context(reqs, g) propagation = EBGPPropagation(reqs, g, ctx) unmatching_order = propagation.compute_dags() assert not unmatching_order propagation.synthesize() solver = z3.Solver(ctx=ctx.z3_ctx) ret = ctx.check(solver) assert ret == z3.sat, solver.unsat_core() print solver.model() propagation.update_network_graph() gns3 = GNS3Topo(g, prefix_map) gns3.write_configs('./out-configs/good_gadget')
def test_next_hop_mixed_route_map(self): # Arrange graph, (ann1, ann2, ann3) = self.get_cust_peer_linear_topo() r1, r2, provider1, provider2, customer = 'R1', 'R2', 'Provider1', 'Provider2', 'Customer' prefix1 = ann1.prefix prefix2 = ann3.prefix graph.add_bgp_advertise(node=provider1, announcement=ann1, loopback='lo10') graph.add_bgp_advertise(node=provider2, announcement=ann2, loopback='lo10') #graph.add_bgp_advertise(node=customer, announcement=ann3, loopback='lo10') clist = CommunityList(list_id=1, access=Access.permit, communities=[VALUENOTSET]) match = MatchCommunitiesList(clist) graph.add_bgp_community_list(r1, clist) rline1 = RouteMapLine(matches=[match], actions=[], access=VALUENOTSET, lineno=10) rline2 = RouteMapLine(matches=[], actions=[], access=Access.permit, lineno=100) rmap_export = RouteMap(name='DenyExport', lines=[rline1, rline2]) graph.add_route_map(r1, rmap_export) graph.add_bgp_export_route_map(r1, provider1, rmap_export.name) graph.add_bgp_export_route_map(r1, provider2, rmap_export.name) # Custom match iplist = IpPrefixList(name='L1', access=Access.permit, networks=[VALUENOTSET]) graph.add_ip_prefix_list(r1, iplist) match = MatchIpPrefixListList(iplist) actions = [ActionSetLocalPref(VALUENOTSET), ActionSetCommunity(communities=[VALUENOTSET])] rline1 = RouteMapLine(matches=[match], actions=actions, access=VALUENOTSET, lineno=10) rline2 = RouteMapLine(matches=[], actions=[], access=Access.deny, lineno=100) rmap_import = RouteMap(name='Import', lines=[rline1, rline2]) graph.add_route_map(r1, rmap_import) graph.add_bgp_import_route_map(r1, provider1, rmap_import.name) graph.add_bgp_import_route_map(r1, provider2, rmap_import.name) p1 = PathReq(Protocols.BGP, dst_net=prefix1, path=[customer, r2, r1, provider1], strict=False) p2 = PathReq(Protocols.BGP, dst_net=prefix1, path=[customer, r2, r1, provider1], strict=False) req1 = PathOrderReq(Protocols.BGP, prefix1, [p2, p1], strict=False) netcomplete = NetComplete([req1], graph, [ann1, ann2]) next_hop_vals = { 'R1': 'Provider1-Fa0-0', 'R2': 'Provider1-Fa0-0', 'Customer': 'R2-Fa0-0', 'Provider1': '0.0.0.0', 'Provider2': '0.0.0.0', } provider1_as = [graph.get_bgp_asnum(provider1)] + ann1.as_path provider2_as = [graph.get_bgp_asnum(provider2)] + ann2.as_path r1_as = [graph.get_bgp_asnum(r1)] + provider1_as customer_as = [graph.get_bgp_asnum(customer)] + r1_as as_path_vals = { 'R1': 'as_path_{}'.format('_'.join([str(x) for x in r1_as])), 'R2': 'as_path_{}'.format('_'.join([str(x) for x in r1_as])), 'Customer': 'as_path_{}'.format('_'.join([str(x) for x in customer_as])), 'Provider1': 'as_path_{}'.format('_'.join([str(x) for x in provider1_as])), 'Provider2': 'as_path_{}'.format('_'.join([str(x) for x in provider2_as])), } as_path_len_vals = { 'R1': len(r1_as) - 1, 'R2': len(r1_as) - 1, 'Customer': len(customer_as) - 1, 'Provider1': len(provider1_as) - 1, 'Provider2': len(provider2_as) - 1, } # Act ret = netcomplete.synthesize() netcomplete.write_configs('out-configs/ibgp') # Assert self.assertTrue(ret) for node, attrs in netcomplete.bgp_synthesizer.ibgp_propagation.nodes(data=True): for ann in attrs['box'].selected_sham: self.assertTrue(ann.permitted.is_concrete) self.assertTrue(ann.permitted.get_value()) self.assertTrue(ann.prefix.is_concrete) self.assertEquals(desanitize_smt_name(ann.prefix.get_value()), prefix1) self.assertTrue(ann.next_hop.is_concrete) self.assertEquals(desanitize_smt_name(ann.next_hop.get_value()), next_hop_vals[node]) self.assertTrue(ann.as_path.is_concrete) self.assertEquals(ann.as_path.get_value(), as_path_vals[node]) self.assertTrue(ann.as_path_len.is_concrete) self.assertEquals(ann.as_path_len.get_value(), as_path_len_vals[node]) self.assertTrue(ann.med.is_concrete) self.assertEquals(ann.med.get_value(), DEFAULT_MED) self.assertTrue(ann.local_pref.is_concrete) #self.assertEquals(ann.local_pref.get_value(), DEFAULT_LOCAL_PREF) for comm, val in ann.communities.iteritems(): self.assertTrue(val.is_concrete)
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)