def stop_network(self): if not self.net_stopped: self.net_stopped = True log.info("Removing interfaces and restoring all network state.") if self.tcp_policy == "dctcp": dc_utils.exec_process("sysctl -w net.ipv4.tcp_ecn=0") # reset the active host congestion control to the previous value cmd = "sysctl -w net.ipv4.tcp_congestion_control=%s" % self.prev_cc dc_utils.exec_process(cmd) log.info("Deleting the virtual network") self.net.stop() log.info("Successfully deleted the virtual network")
def load_congestion_control(tcp_policy): if tcp_policy == "dctcp": dc_utils.exec_process("modprobe tcp_dctcp") dc_utils.exec_process("sysctl -w net.ipv4.tcp_ecn=1") elif tcp_policy == "tcp_nv": dc_utils.exec_process("modprobe tcp_nv") elif tcp_policy == "pcc": if (os.popen("lsmod | grep pcc").read() == ""): dc_utils.exec_process("insmod %s/tcp_pcc.ko" % FILE_DIR)
def record_rate(in_rate, ctrl_rate, sleep, out_dir): # Convert to human readable format ctrl_rate = ctrl_rate * (in_rate / 1e3) in_rate = in_rate / 1e6 log.info(f"Input: {in_rate} Mbps Expected: {ctrl_rate} kbps") log.info(f"Waiting for {sleep} seconds...") out_dir = "control_test" out_file = f"{out_dir}/{in_rate}mbps_in_{ctrl_rate}kbps_expected" dc_utils.check_dir(out_dir) ifstat_cmd = "ifstat -b " ifstat_cmd += "-i s1-eth1 " # interface to listen on ifstat_cmd += "-q 1 " # measurement interval ifstat_cmd += "%d " % sleep # measure how long return dc_utils.exec_process(ifstat_cmd, out_file=out_file)
def _install_proactive(self): """ Install proactive flow entries for the switch. """ protocols = ["ip", "arp"] # West Switch ovs_flow_cmd = "ovs-ofctl add-flow %s " % self.core_switch ovs_flow_cmd += "-O OpenFlow13 " for prot in protocols: i = 1 j = 1 for k in range(1, self.conf["num_hosts"] + 1): cmd = ovs_flow_cmd cmd += "table=0,idle_timeout=0," cmd += "hard_timeout=0,priority=10," cmd += "nw_dst=10.%d.0.%d," % (i, j) cmd += "%s," % prot cmd += "actions=output:%d" % k dc_utils.exec_process(cmd) j += 1 if j == 3: j = 1 i += 1
def _start_pkt_capture_tshark(self, out_dir): # start a tshark capture process dmp_file = "%s/pkt_snapshot.pcap" % (out_dir) dmp_cmd = "tshark " for host_iface in self.net_man.host_ctrl_map: dmp_cmd += "-i %s " % host_iface dmp_cmd += "-w %s " % dmp_file dmp_cmd += "-f %s " % self.transport # filter transport protocol dmp_cmd += "-b duration:300 " # reset pcap file after 300s dmp_cmd += "-b filesize:%d " % 10e5 # reset pcap file after 1GB dmp_cmd += "-b files:1 " # only write one capture file dmp_cmd += "-B 500 " # mb size of the packet buffer dmp_cmd += "-q " # do not log.info to stdout dmp_cmd += "-n " # do not resolve hosts dmp_cmd += "-F pcapng " # format of the capture file dmp_proc = dc_utils.exec_process(dmp_cmd, out_file=dmp_file) self.service_procs.append(dmp_proc)
def _install_proactive(self): """ Install proactive flow entries for the switch. """ protocols = ["ip", "arp"] for prot in protocols: # West Switch ovs_flow_cmd = "ovs-ofctl add-flow %s " % self.switch_w ovs_flow_cmd += "-O OpenFlow13 " for index, host in enumerate(self.hosts_w): port = index + 2 host_ip = self.host_ips[host] cmd = ovs_flow_cmd cmd += "table=0,idle_timeout=0," cmd += "hard_timeout=0,priority=10," cmd += "%s," % prot cmd += "nw_dst=%s," % host_ip cmd += "actions=output:%d" % port dc_utils.exec_process(cmd) cmd = ovs_flow_cmd cmd += "table=0,idle_timeout=0,hard_timeout=0,priority=10," cmd += "%s," % prot cmd += "nw_dst=10.2.0.0/16,actions=output:1" dc_utils.exec_process(cmd) # East Switch ovs_flow_cmd = "ovs-ofctl add-flow %s " % self.switch_e ovs_flow_cmd += "-O OpenFlow13 " for index, host in enumerate(self.hosts_e): port = index + 2 host_ip = self.host_ips[host] cmd = ovs_flow_cmd cmd += "table=0,idle_timeout=0," cmd += "hard_timeout=0,priority=10," cmd += "%s," % prot cmd += "nw_dst=%s," % host_ip cmd += "actions=output:%d" % port dc_utils.exec_process(cmd) cmd = ovs_flow_cmd cmd += "table=0,idle_timeout=0,hard_timeout=0,priority=10," cmd += "%s," % prot cmd += "nw_dst=10.1.0.0/16,actions=output:1" dc_utils.exec_process(cmd)
def _install_proactive(self): """ Install proactive flow entries for switches. """ protocols = ["ip", "arp"] switches = self.edge_switches + self.agg_switches + self.core_switches for sw in switches: num = int(sw[-1:]) ovs_flow_cmd = "ovs-ofctl add-flow %s -O OpenFlow13 " % sw ovs_grp_cmd = "ovs-ofctl add-group %s -O OpenFlow13 " % sw # Set upstream links of lower level switches if sw in self.edge_switches or sw in self.agg_switches: cmd = ovs_grp_cmd cmd += "group_id=1,type=select," cmd += "bucket=output:1,bucket=output:2" if self.fanout == 8: cmd += ",bucket=output:3,bucket=output:4" dc_utils.exec_process(cmd) # Configure entries per protocol for prot in protocols: cmd = ovs_flow_cmd cmd += "table=0,priority=10,%s,actions=group:1" % prot dc_utils.exec_process(cmd) # Configure entries per protocol for prot in protocols: # Edge Switches if sw in self.edge_switches: # Set downstream links for i in range(1, self.density + 1): cmd = ovs_flow_cmd cmd += "table=0,idle_timeout=0," cmd += "hard_timeout=0,priority=40," cmd += "%s," % prot cmd += "nw_dst=10.%d.0.%d," % (num, i) cmd += "actions=output:%d" % (self.fanout / 2 + i) dc_utils.exec_process(cmd) # Aggregation Switches if sw in self.agg_switches: # Set downstream links subnetList = self.create_subnet_list(num) k = 1 for i in subnetList: cmd = ovs_flow_cmd cmd += "table=0,idle_timeout=0," cmd += "hard_timeout=0,priority=40," cmd += "%s," % prot cmd += "nw_dst=10.%d.0.0/16," % i cmd += "actions=output:%d" % (self.fanout / 2 + k) dc_utils.exec_process(cmd) k += 1 # Core Switches if sw in self.core_switches: # Set downstream links j = 1 k = 1 for i in range(1, len(self.edge_switches) + 1): cmd = ovs_flow_cmd cmd += "table=0,idle_timeout=0," cmd += "hard_timeout=0,priority=10," cmd += "%s," % prot cmd += "nw_dst=10.%d.0.0/16," % i cmd += "actions=output:%d" % j dc_utils.exec_process(cmd) k += 1 if k == self.fanout / 2 + 1: j += 1 k = 1
def _apply_qdisc(self, port): """ Here be dragons... """ # tc_cmd = "tc qdisc add dev %s " % (port) # cmd = "root handle 1: hfsc default 10" # log.info(tc_cmd + cmd) # dc_utils.exec_process(tc_cmd + cmd) # tc_cmd = "tc class add dev %s " % (port) # cmd = "parent 1: classid 1:10 hfsc sc rate %dbit ul rate %dbit" % ( # self.topo.max_bps, self.topo.max_bps) # log.info(tc_cmd + cmd) # dc_utils.exec_process(tc_cmd + cmd) limit = int(self.topo.max_queue) avg_pkt_size = 1500 # MTU packet size tc_cmd = "tc qdisc add dev %s " % (port) cmd = "root handle 1: htb default 10 " # cmd = "root handle 1: estimator 250msec 1sec htb default 10 " cmd += " direct_qlen %d " % (limit / avg_pkt_size) log.debug(tc_cmd + cmd) dc_utils.exec_process(tc_cmd + cmd) tc_cmd = "tc class add dev %s " % (port) cmd = "parent 1: classid 1:10 htb rate %dbit burst %d" % ( self.topo.max_bps, self.topo.max_bps) log.debug(tc_cmd + cmd) dc_utils.exec_process(tc_cmd + cmd) if self.tcp_policy == "dctcp": marking_threshold = calc_ecn(self.topo.max_bps, avg_pkt_size) # Apply aggressive RED to mark excess packets in the queue max_q = limit / 4 min_q = int(marking_threshold) tc_cmd = "tc qdisc add dev %s " % (port) cmd = "parent 1:10 handle 20:1 red " cmd += "limit %d " % (limit) cmd += "bandwidth %dbit " % self.topo.max_bps cmd += "avpkt %d " % avg_pkt_size cmd += "min %d " % min_q cmd += "max %d " % max_q # Ballpark burst hard limit... burst = (min_q + min_q + max_q) / (3 * avg_pkt_size) cmd += "burst %d " % burst cmd += "probability 0.1" cmd += " ecn " log.debug(tc_cmd + cmd) dc_utils.exec_process(tc_cmd + cmd) else: tc_cmd = "tc qdisc add dev %s " % (port) cmd = "parent 1:10 handle 20:1 bfifo " cmd += " limit %d" % limit dc_utils.exec_process(tc_cmd + cmd) # tc_cmd = "tc qdisc add dev %s " % (port) # cmd = "root handle 1 netem limit %d rate 10mbit" % ( # limit / avg_pkt_size) # log.info(tc_cmd + cmd) # dc_utils.exec_process(tc_cmd + cmd) # limit = int(self.topo.max_queue) # tc_cmd = "tc qdisc add dev %s " % (port) # cmd = "parent 1:10 handle 20: codel " # cmd += " limit %d" % (limit) # dc_utils.exec_process(tc_cmd + cmd) # limit = int(self.topo.max_queue) # max_q = self.topo.max_queue / 4 # min_q = max_q / 3 # tc_cmd = "tc qdisc add dev %s " % (port) # cmd = "parent 1:10 handle 20:1 sfq limit %d" % ( # self.topo.max_queue) # if self.dctcp: # dc_utils.exec_process("sysctl -w net.ipv4.tcp_ecn=1") # cmd += "ecn " # # cmd += "redflowlimit " # # cmd += "min %d " % (min_q) # # cmd += "max %d " % (max_q) # # cmd += "probability 1" # log.info(tc_cmd + cmd) # dc_utils.exec_process(tc_cmd + cmd) # Apply tc choke to mark excess packets in the queue with ecn # limit = int(self.topo.max_queue) # max_q = self.topo.max_queue # min_q = 400 # tc_cmd = "tc qdisc add dev %s " % (port) # cmd = "parent 1:10 handle 10:1 choke limit %d " % limit # cmd += "bandwidth %dbit " % self.topo.max_bps # cmd += "min %d " % (min_q) # cmd += "max %d " % (max_q) # cmd += "probability 0.001" # # if self.dctcp: # cmd += " ecn " # log.info(tc_cmd + cmd) # dc_utils.exec_process(tc_cmd + cmd) # tc_cmd = "tc qdisc add dev %s " % (port) # cmd = "parent 1:10 handle 30:1 fq_codel limit %d " % ( # self.topo.max_queue) # if ("dctcp" in self.conf) and self.conf["dctcp"]: # dc_utils.exec_process("sysctl -w net.ipv4.tcp_ecn=1") # cmd += "ecn " # log.info(tc_cmd + cmd) # dc_utils.exec_process(tc_cmd + cmd) dc_utils.exec_process("ip link set %s txqueuelen %d" % (port, limit / avg_pkt_size)) dc_utils.exec_process("ip link set %s mtu 1500" % port)
def _config_hosts(self, net): for host in net.hosts: # Increase the maximum total buffer-space allocatable # This is measured in units of pages (4096 bytes) dc_utils.exec_process("sysctl -w net.ipv4.tcp_window_scaling=1", host) dc_utils.exec_process("sysctl -w net.ipv4.tcp_timestamps=1", host) dc_utils.exec_process("sysctl -w net.ipv4.tcp_sack=1", host) dc_utils.exec_process("sysctl -w net.ipv4.tcp_syn_retries=10", host) # dc_utils.exec_process( # "sysctl -w net.core.default_qdisc=pfifo_fast", host) # dc_utils.exec_process("sysctl -w net.ipv4.tcp_recovery=0") if self.tcp_policy == "dctcp": dc_utils.exec_process( "sysctl -w net.ipv4.tcp_congestion_control=dctcp", host) dc_utils.exec_process("sysctl -w net.ipv4.tcp_ecn=1", host) dc_utils.exec_process("sysctl -w net.ipv4.tcp_ecn_fallback=0", host) elif self.tcp_policy == "tcp_nv": dc_utils.exec_process( "sysctl -w net.ipv4.tcp_congestion_control=nv", host) elif self.tcp_policy == "pcc": dc_utils.exec_process( "sysctl -w net.ipv4.tcp_congestion_control=pcc", host)