Example #1
0
def initializeExperiment(image, cc=DEFAULT_CC, sync=False):
    global IMAGE, START_TIME
    IMAGE = image
    START_TIME = datetime.datetime.now()
    print '--- starting experiment...'
    print '--- clearing local arp...'
    call([os.path.expanduser('/etalon/bin/arp_clear.sh')])
    print '--- done...'

    print '--- populating physical hosts...'

    del PHYSICAL_NODES[:]  # clear in place
    PHYSICAL_NODES.append('')
    for i in xrange(1, NUM_RACKS + 1):
        PHYSICAL_NODES.append(get_phost_from_id(i))
    print '--- done...'

    print '--- connecting to rpycd...'
    connect_all_rpyc_daemon()
    print '--- done...'

    print '--- setting CC to {}...'.format(cc)
    setCC(cc, sync)
    print '--- done...'

    print '--- building etalon docker image...'
    if not os.path.isfile(DID_BUILD_FN):
        gen_slaves_file(SLAVES_FILE)
        runWriteFile(DOCKER_BUILD, None)
        print '--- done...'

        print '--- copying image to physical hosts...'
        push_docker_image()
        print '--- done...'
    else:
        print '--- skipping (delete %s to force update)...' % (DID_BUILD_FN)

    print '--- launching containers...'
    launch_all_racks(image, sync)
    print '--- done...'

    click_common.initializeClickControl()

    print '--- setting default click buffer sizes and traffic sources...'
    click_common.setConfig({'cc': cc})
    print '--- done...'
    time.sleep(2)
    print '--- done starting experiment...'
    print
    print
Example #2
0
def main():
    common.initializeExperiment("flowgrindd", cc=CC)

    for typ in ["no_circuit", "circuit", "strobe"]:
        cnf = {
            "type": typ,
            "cc": CC,
            "buffer_size": BUFFER_SIZE,
            "divert_acks": True
        }
        click_common.setConfig(cnf)
        print("--- config:\n{}".format(cnf))
        common.flowgrind(settings={"flows": [{"src": "r1", "dst": "r2"}]})

    common.finishExperiment()
Example #3
0
def main():
    cnfs = buffer_common.gen_static_sweep(2, 7) + buffer_common.gen_resize_sweep(0, 8000, 500)
    # Use the first experiment's CC mode, or "reno" if no CC mode is specified.
    # This avoid unnecessarily restarting the cluster.
    common.initializeExperiment('flowgrindd', cnfs[0].get("cc", "reno"))

    # For every configuration, add a copy that uses reTCP as the CC mode. Put
    # the new configurations at the end so that the CC mode needs to be changed
    # only once.
    cnfs += [dict(cnf, {'cc': "retcp"}) for cnf in cnfs]
    tot = len(cnfs)
    for cnt, cnf in enumerate(cnfs, 1):
        print('--- running test type {}...'.format(cnf['type']))
        print('--- setting switch buffer size to {}...'.format(
            cnf['buffer_size']))
        click_common.setConfig(cnf)
        print('--- done...')
        print("--- experiment {} of {}".format(cnt, tot))
        common.flowgrind(settings={"flows": [{"src": "r1", "dst": "r2"}]})

    common.finishExperiment()
Example #4
0
def main():
    # Generate the list of configurations first so that we know the total number
    # of experiments. CC modes are the outside loop to minimize how frequently
    # we change the CC mode, since doing so requires restarting the cluster.
    # ccs = python_config.CCS
    ccs = ["cubic"]
    cnfs = []
    for cc in ccs:
        # sweep = buffer_common.gen_static_sweep(4, 12)
        sweep = buffer_common.gen_resize_sweep(
            int(round(RESIZE_US_MIN * python_config.TDF)),
            int(round(RESIZE_US_MAX * python_config.TDF)),
            int(round(RESIZE_US_DELTA * python_config.TDF)))

        for cnf in sweep:
            cnf["cc"] = cc
            if cc == "dctcp":
                # For DCTCP, enable threshold-based ECN marking.
                cnf['ecn'] = python_config.DCTCP_THRESH
            if FIXED is not None:
                cnf["type"] = "fixed"
                cnf["fixed_schedule"] = FIXED
        cnfs += sweep
    # Total number of experiments.
    tot = len(cnfs)

    # Use the first CC mode when starting the cluster to avoid needing to
    # restart the cluster for the first CC mode's experiments.
    maybe(lambda: common.initializeExperiment("flowgrindd", ccs[0]))
    for cnt, cnf in enumerate(cnfs, 1):
        maybe(lambda: click_common.setConfig(cnf))
        print("--- experiment {} of {}, config:\n{}".format(cnt, tot, cnf))
        maybe(lambda: common.flowgrind(settings={
            "flows": [{
                "src": "r1",
                "dst": "r2"
            }],
            "dur": DUR_S
        }))
    maybe(common.finishExperiment)
Example #5
0
        'buffer_size': 16,
        'in_advance': 20000,
        'queue_resize': True
    },
]

#               0.5    1    1.5    2     3     4     6      8      12
link_delays = [1e-4, 2e-4, 3e-4, 4e-4, 6e-4, 8e-4, 12e-4, 16e-4, 24e-4]
sched = ['strobe']

initializeExperiment('flowgrindd')

for t in sched:
    for d in link_delays:
        for config in CONFIGS:
            config['circuit_link_delay'] = d
            config['type'] = t
            if t == 'short_reconfig' and 'in_advance' in config:
                config['in_advance'] = 10000
            print '--- running test type %s...' % config['type']
            print '--- setting switch buffer size to %d...' % \
                config['buffer_size']
            setConfig(config)
            print '--- done...'

            settings = {'flows': []}
            settings['flows'].append({'src': 'r1', 'dst': 'r2'})
            flowgrind(settings)

finishExperiment()
Example #6
0
def main():
    # Experiments:
    # (1) Long nights/days, static buffers. CUBIC. Old optical switches.
    # (2) Very short nights/days, static buffers, CUBIC. Future optical
    #     switches.
    # (3) Short nights/days, static buffers, all TCP variants.
    # (4) Short nights/days, dynamic buffers, all TCP variants.
    # (5) Vary night/day length, static buffers + CUBIC and dynamic buffers + reTCP.

    # Assemble configurations. Generate the list of configurations first so that
    # we know the total number of experiments.
    cnfs = []
    # CC modes are the outside loop to minimize how frequently we change the CC
    # mode, since doing so requires restarting the cluster.
    for cc in python_config.CCS:
        # if cc in ["cubic"]:
        #     # (1) Old switches.
        #     cnfs += [{"type": "fake_strobe",
        #               "num_racks_fake": NUM_RACKS_FAKE,
        #               "night_len_us": 1000 * python_config.TDF,
        #               "day_len_us": 9000 * python_config.TDF,
        #               "cc": cc}]
        #     # (2) Future switches.
        #     cnfs += [{"type": "fake_strobe",
        #               "num_racks_fake": NUM_RACKS_FAKE,
        #               "night_len_us": 1 * python_config.TDF,
        #               "day_len_us": 9 * python_config.TDF, "cc": cc}]
        # # (3) Static buffers.
        # for exp in xrange(2, STATIC_POW_MAX + 1):
        #     # Only do full sweeps for CUBIC and reTCP, but capture 16 packets
        #     # for all variants.
        #     if cc in ["cubic", "retcp"] or exp == 4:
        #         cnfs += [{"type": "fake_strobe",
        #                   "num_racks_fake": NUM_RACKS_FAKE,
        #                   "small_queue_cap": 2**exp,
        #                   "big_queue_cap": 2**exp,
        #                   "cc": cc}]
        # # (4) Long prebuffering.
        # for us in xrange(RESIZE_LONG_MIN_us, RESIZE_LONG_MAX_us + 1,
        #                  RESIZE_LONG_DELTA_us):
        #     # Only do a full sweep for CUBIC, but capture a few key us's for all
        #     # variants.
        #     if cc == "cubic" or us in ALL_VARIANTS_uss:
        #         cnfs += [{"type": "fake_strobe",
        #                   "num_racks_fake": NUM_RACKS_FAKE,
        #                   "queue_resize": True,
        #                   "in_advance": int(round(us * python_config.TDF)),
        #                   "cc": cc}]
        # # (4) Short prebuffering, only for reTCP.
        # if cc == "retcp":
        #     for us in xrange(RESIZE_SHORT_MIN_us, RESIZE_SHORT_MAX_us + 1,
        #                      RESIZE_SHORT_DELTA_us):
        #         cnfs += [{"type": "fake_strobe",
        #                   "num_racks_fake": NUM_RACKS_FAKE,
        #                   "queue_resize": True,
        #                   "in_advance": int(round(us * python_config.TDF)),
        #                   "cc": cc}]
        # (5) Vary night len.
        for exp in xrange(NIGHT_LEN_POW_MIN, NIGHT_LEN_POW_MAX + 1):
            night_len_us = 2**exp
            day_len_us = 9 * night_len_us
            night_len_us_tdf = int(round(night_len_us * python_config.TDF))
            day_len_us_tdf = int(round(day_len_us * python_config.TDF))
            # CUBIC with static buffers.
            if cc == "cubic":
                cnfs += [{
                    "type": "fake_strobe",
                    "num_racks_fake": NUM_RACKS_FAKE,
                    "small_queue_cap": SMALL_QUEUE_CAP,
                    "big_queue_cap": SMALL_QUEUE_CAP,
                    "night_len_us": night_len_us_tdf,
                    "day_len_us": day_len_us_tdf,
                    "cc": cc
                }]
            # reTCP with dynamic buffers.
            if cc == "retcp":
                cnfs += [{
                    "type":
                    "fake_strobe",
                    "num_racks_fake":
                    NUM_RACKS_FAKE,
                    "small_queue_cap":
                    SMALL_QUEUE_CAP,
                    "big_queue_cap":
                    BIG_QUEUE_CAP,
                    "night_len_us":
                    night_len_us_tdf,
                    "day_len_us":
                    day_len_us_tdf,
                    "queue_resize":
                    True,
                    # Use 150us or 75% of the circuit downtime length,
                    # whichever is less.
                    "in_advance":
                    int(
                        round(
                            min(
                                0.75 *
                                ((NUM_RACKS_FAKE - 1) *
                                 (night_len_us + day_len_us) - day_len_us),
                                RETCP_RESIZE_us) * python_config.TDF)),
                    "cc":
                    cc
                }]

    # Set paramters that apply to all configurations.
    for cnf in cnfs:
        # Enable the hybrid switch's packet log. This should already be enabled
        # by default.
        cnf["packet_log"] = True
        # If the night and day lengths have not been set already, then do so
        # here. Explicitly set the night and day lengths instead of relying on
        # their defaults so that we can automatically calculate the experiment
        # duration, below.
        if "night_len_us" not in cnf:
            cnf["night_len_us"] = int(round(20 * python_config.TDF))
            cnf["day_len_us"] = int(round(180 * python_config.TDF))
        if "small_queue_cap" not in cnf:
            cnf["small_queue_cap"] = SMALL_QUEUE_CAP
            cnf["big_queue_cap"] = BIG_QUEUE_CAP
        if cnf["cc"] == "dctcp":
            # If the configuration uses DCTCP, then enable threshold-based ECN
            # marking.
            cnf["ecn"] = (python_config.DCTCP_THRESH,
                          int(
                              round(
                                  float(cnf["big_queue_cap"]) /
                                  cnf["small_queue_cap"] *
                                  python_config.DCTCP_THRESH)))

    # Assemble settings. Generate the list of settings first so that we can
    # the estimated total duration.
    cnfs = [
        (
            cnf,
            {
                # Generate a flow from each machine on rack 1 to its corresponding
                # partner machine on rack 2.
                "flows": [{
                    "src": "r2",
                    "dst": "r3"
                }],
                # Run the flow for three thousand weeks plus 100 ms for good
                # measure, converted to seconds. The resulting duration is not under
                # TDF, but the flow will be under TDF when it is executed (i.e., the
                # flow will actually take TDF times longer than the value computed
                # here).
                "dur":
                (((cnf["night_len_us"] + cnf["day_len_us"]
                   )  # One night and day under TDF.
                  / python_config.TDF  # Convert from TDF to real time.
                  * (cnf["num_racks_fake"] - 1)  # Convert to a full week.
                  / 1e3  # Convert from us to ms.
                  * 3000  # 3000 weeks.
                  + 100)  # Extra 100 ms, for good measure.
                 / 1e3),  # Convert to seconds.
                "tcpdump":
                TCPDUMP
            }) for cnf in cnfs
    ]

    # Total number of experiments.
    tot = len(cnfs)
    # Estimated total duration.
    dur = sum([stg["dur"] for cnf, stg in cnfs]) * python_config.TDF
    print("Estimated total duration: > {:.2f} seconds, > {:.2f} hours".format(
        dur, dur / 3600.))
    # Run experiments. Use the first experiment's CC mode to avoid unnecessarily
    # restarting the cluster.
    maybe(lambda: common.initializeExperiment(
        "flowgrindd", cc=cnfs[0][0]["cc"], sync=SYNC))
    for cnt, (cnf, stg) in enumerate(cnfs, start=1):
        maybe(lambda: click_common.setConfig(cnf))
        print("--- experiment {} of {}, config:\n{}".format(cnt, tot, cnf))
        maybe(lambda: common.flowgrind(settings=stg))
    maybe(common.finishExperiment)
Example #7
0
        'in_advance': 20000,
        'cc': 'retcp'
    },
]

for c in CONFIGS:
    c['packet_log'] = False
    if c['type'] == 'resize':
        c['type'] = 'normal'
        c['queue_resize'] = True
    else:
        c['queue_resize'] = False
    if 'cc' not in c:
        c['cc'] = 'reno'
    c['thresh'] = 8000

for h in ['HDFS', 'reHDFS']:
    for c in CONFIGS:
        c['hdfs'] = h
        print '--- running %s, %s, %s, %s' % (h, c['traffic_source'],
                                              c['queue_resize'], c['cc'])
        if c['traffic_source'] == 'ADU':
            initializeExperiment(h + "_adu")
        else:
            initializeExperiment(h)
        setConfig(c)
        print '--- done initializing...'
        dfsioe('h21', h)

finishExperiment()