def runstuff(): NUM_SWITCHES = 20 # total number of switches in the complete graph of switch-port connectivity NUM_CLIENTS = 2 # number of clients on every switch. large numbers will decrease the size of sccs, because # forwarding to clients is always safe; not part of a loop. RULES_PER_ROUND = 350 # number of rule installs to do between gathering time statistics. MAX_TOTAL_RULES_INSTALLED = 450 # number of total rules to maintain in the network model, so # that as more than these come in, we evict the oldest ones. TOTAL_RULE_INSTALLATIONS_BEFORE_HALT = 350 # halt after this many total rule installations. SHOW_TRACE = False # should we show the trace when loops are detected? This can get hectic. MIN_IN = 1 # minininum number of in_ports to be used in random rules. MAX_IN = 3 # etc. MIN_OUT = 1 MAX_OUT = 2 # the network that we'kll use to generate random valid rules net = TestNetwork1(NUM_SWITCHES, NUM_CLIENTS, minswitch=5555, minport=100001) # our model n = NetworkFlowruleModel() # track the flow install rate in this timestats = StatsBuddy() total_installed = 0 # track the rules in place in our NetworkFlowruleModel so we can evict them q = Queue.Queue() while True: #start a timer t1 = time.time() # do some rule installations for r in xrange(RULES_PER_ROUND): if q.qsize() > MAX_TOTAL_RULES_INSTALLED: droprule = q.get() # get the number of the rule that's over the limit n.drop_flow_rule(droprule) # kill the rule rule = net.get_random_rule(MIN_IN, MAX_IN, MIN_OUT, MAX_OUT) (rnum, trace) = n.install_flow_rule(rule) if SHOW_TRACE and trace: NetworkFlowruleModel.explain(trace) q.put(rnum) total_installed += 1 t2 = time.time() # NOTE: linux might report this in ms instead of seconds, I think, # so this might give weird results timestats.add(RULES_PER_ROUND/(t2-t1)) # how we eventually halt if total_installed >= TOTAL_RULE_INSTALLATIONS_BEFORE_HALT: break print timestats, 'are stats for the number of rule installs and evictions per second.' print n.sccsizestats, 'are stats for the average scc size of installed rules.' return
def RunTest(num_switches, num_clients, steady_state_avg_rules_per_switch, total_rule_installations_before_halt, min_in, max_in, min_out, max_out, min_match_bits=0, max_match_bits=0, min_rewrite_bits=0, max_rewrite_bits=0, show_trace = False, port_density = 1.0, rewrite_rule_probability = 1.0): """ num_switches: total number of switches in the complete graph of switch-port connectivity num_clients: number of clients on every switch. large numbers will decrease the size of sccs, because forwarding to clients is always safe; not part of a loop. steady_state_avg_rules_per_switch: The average number of rules to keep in the network per switch before rules are evicted The network will gradually be built up to have steady_state_avg_rules_per_switch * num_switches and then exist with that steady state number of rules until the total number of rule installations occurs total_rule_installations_before_halt: Halt after this many total rule installations. (Will be rounded to a multiple of 20, to make progress reporting cleaner) min_in: Minininum number of in_ports to be used in random rules max_in: etc. min_out: etc. max_out: etc. min_match_bits: The minimum number of bits to fix as non-'x' in random rewrite rule matchs max_match_bits: Max of above min_rewrite_bits: The minimum number of bits to explicitly fix randomly as one of 0/1 in output packets max_rewrite_bits: Max of above show_trace: Should we show the trace when loops are detected? This can get hectic and start spinning the terminal. port_density: Default of 1.0, indicating the complete graph as the underlying network topology For less than that, the network is a ring with _this_ proportion of the pairs of switches connected by a pair of 1-way ports. rewrite_rule_probability: The proportion of the random rules that should be random rewrite rules rather than random forwarding rules """ # some basic info for our run steady_state_rules_in_network = num_switches * steady_state_avg_rules_per_switch rules_per_round = total_rule_installations_before_halt / 20 total_rule_installations_before_halt = rules_per_round * 20 # eject if params are silly if total_rule_installations_before_halt <= steady_state_rules_in_network: raise Exception('The given parameters will not permit the network to reach a steady state, so no statistics would be collected. Try decreasing "steady_state_avg_rules_per_switch".') # the network that we'll use to generate random valid rules net = TestNetwork(num_switches, num_clients, port_density) # our model n = NetworkFlowruleModel() # annotate the parameters print 'Parameters for this run are:', (num_switches, num_clients, steady_state_avg_rules_per_switch, total_rule_installations_before_halt, min_in, max_in, min_out, max_out, min_match_bits, max_match_bits, min_rewrite_bits, max_rewrite_bits, show_trace, port_density, rewrite_rule_probability) print 'Steady state will have {} rules installed.'.format(steady_state_rules_in_network) #start a timer test_start_time = time.time() steady_state_start_time = None # we'll set this when we reach maximum flow capacity for the network total_installed = 0 # track the rules in place in our NetworkFlowruleModel so we can evict them q = Queue.Queue() while total_installed < total_rule_installations_before_halt: # do some rule installations for r in xrange(rules_per_round): # drop rules so we don't exceed steady_state_rules_in_network if q.qsize() > steady_state_rules_in_network: droprule = q.get() # get the number of the rule that's over the limit n.drop_flow_rule(droprule) # kill the rule if steady_state_start_time is None: n.collect_stats(True) steady_state_start_time = time.time() ###################################### if rand.random() <= rewrite_rule_probability: rule = net.get_random_rewrite_rule(min_in, max_in, min_out, max_out, min_match_bits, max_match_bits, min_rewrite_bits, max_rewrite_bits) else: rule = net.get_random_rule(min_in, max_in, min_out, max_out) ###################################### # put the random flow into our model (rnum, trace) = n.install_flow_rule(rule) # show detected loop details if desired if show_trace and trace: NetworkFlowruleModel.explain(trace) q.put(rnum) total_installed += 1 amount_done = 1.0 * total_installed / total_rule_installations_before_halt if steady_state_start_time is not None: time_in_steady_state = time.time() - steady_state_start_time amount_of_steady_state_done = 1.0 * (total_installed - steady_state_rules_in_network) / (total_rule_installations_before_halt - steady_state_rules_in_network) expected_steady_state_time_total = time_in_steady_state / amount_of_steady_state_done expected_remaining_time = expected_steady_state_time_total * (1.0 - amount_of_steady_state_done) print '{:.0%} done. Expected {:.4g}s remaining'.format(amount_done, expected_remaining_time) else: print '{:.0%} done. Steady state not yet entered...'.format(amount_done) test_end_time = time.time() total_test_time = test_end_time - test_start_time steady_state_total_time = test_end_time - steady_state_start_time # show heaps of info about the run print print 'Overall, {:.5g} rules were installed per second on average.'.format(1.0 * total_rule_installations_before_halt / total_test_time) print 'While in steady state, {:.5g} rules were installed per second on average.'.format(1.0 * (total_rule_installations_before_halt - steady_state_rules_in_network) / steady_state_total_time) print n.scc_size_stats, 'are the stats for the average SCC size of installed rules.' print n.edges_stats, 'are the stats for the average number of graph edges added per installed rule.' print 'Loop detection was called for {:.4%} of rule installs'.format(1.0 * n.loop_detection_calls / total_rule_installations_before_halt) print 'Loops were detected for {:.4%} of rule installs'.format(1.0 * n.loops_detected / total_rule_installations_before_halt) print 'Loops were present for {:.4%} of calls to loop detection'.format(1.0 * n.loops_detected / n.loop_detection_calls) print 'SCC sizes are distributed like this:', n.scc_buckets.graph()
def get_network_model(self): n = NetworkFlowruleModel() for rule in self.rules(): (rnum, trace) = n.install_flow_rule(rule) if trace: print NetworkFlowruleModel.explain(trace) return n