Пример #1
0
def convert_topology(edges, hsf, portids):
    """ Convert a list of edges representing the topology into a topology
    transfer function. """
    ttf = TF(hsf["length"] * 2)
    for (s1, p1, s2, p2) in edges:
        rule = TF.create_standard_rule([portids[(s1,p1)]], None,
                                       [portids[(s2,p2)]], None, None)
        ttf.add_link_rule(rule)
        rule = TF.create_standard_rule([portids[(s2,p2)]], None,
                                       [portids[(s1,p1)]], None, None)
        ttf.add_link_rule(rule)
    global TFS_FOLDER
    ttf.save_object_to_file("%s/topology.tf" % TFS_FOLDER)
Пример #2
0
 def init_tfs():
     """ Initialize one transfer function per device. """
     tfs_map = {}
     for sw in sw_ports.keys():
         tfs_map[sw] = TF(hsf["length"])
         tfs_map[sw].set_prefix_id("s%d" % sw)
         tfs_map[sw].set_send_on_receiving_port(True)
     return tfs_map
Пример #3
0
def convert_classifier(classifier, hsf, portids, sw_ports):
    """Function to convert a classifier `classifier` into a header space given by a
    header space format dictionary `hsf`.
    """
    hsalib_log = logging.getLogger('%s.convert_classifier' % __name__)

    def get_action_wc(acts):
        """Return a rewrite mask, rewrite HS, and the list of outports from the
        action list `acts` provided. For interpretation of these fields check
        the doctext of hsa.headerspace.tf create_standard_rule.

        In this function, we assume that the actions correspond to the actions
        of a single-stage table classifier, in addition to other
        restrictions. Specifically:
        - all non-`modify` actions are ignored
        - actions that do not set an output port are ignored
        - if there are multiple actions satisfying the above conditions, they
        may only simply output the packet via a port. i.e., No packet
        modifications. This is an artificial restriction because
        tf.create_standard_rule can only take a single rewrite wildcard for
        packet modification.
        """
        new_acts = filter(lambda x: isinstance(x, modify) and 'port' in x.map,
                          acts)
        outports = []
        '''The current transfer function rule implementation can only take one new
        header space in rewrite rules if there are multiple outports
        involved. If there is only one action, multiple field rewrites are
        possible. A port must be set for rewrites to be active.
        '''
        if len(new_acts) > 1:
            hsa_compilable = reduce(lambda acc, a: acc and
                                    a.map.keys() == ['port'],
                                    new_acts, True)
            outports = map(lambda x: x.map['port'], new_acts)
            if hsa_compilable:
                return (None, None, outports, False)
            else:
                raise RuntimeError("actions not HSA-compilable! %s" % acts)
        elif len(new_acts) == 1:
            mod_dict = copy.copy(new_acts[0].map)
            if 'port' in mod_dict:
                outports = [mod_dict['port']]
                del mod_dict['port']
            else:
                return (None, None, [], False)
            if len(mod_dict.keys()) > 0:
                ''' There are rewritten packet header fields. '''
                rw_rule = True
                mask = wildcard_create_bit_repeat(hsf["length"], 0x2)
                rewrite = wildcard_create_bit_repeat(hsf["length"], 0x1)
                for (field, val) in mod_dict.iteritems():
                    set_field_val(hsf, mask, field, 0, process_field=False)
                    set_field_val(hsf, rewrite, field, val)
                return (mask, rewrite, outports, True)
            else:
                return (None, None, outports, False)
        else:
            ''' No modify actions '''
            return (None, None, [], False)

    def process_outports(mat_map, acts_ports, sw, rule):
        ''' Return network-wide unique port identifiers from the port values
        present in classifier actions. '''
        def warn_nonexistent_port(p):
            print sw_ports
            hsalib_log.warn("Non-existent port specified: "
                            "(sw %d, p %d) in %s" % (
                                sw, p, str(rule)))
        out_ports = []
        for p in acts_ports:
            if p in sw_ports[sw]:
                out_ports.append(portids[(sw,p)])
            elif p == OFPP_IN_PORT:
                if 'port' in mat_map:
                    out_ports.append(portids[(sw,mat_map['port'])])
                else:
                    warn_nonexistent_port(p)
            else:
                warn_nonexistent_port(p)
        return out_ports

    def init_tfs():
        """ Initialize one transfer function per device. """
        tfs_map = {}
        for sw in sw_ports.keys():
            tfs_map[sw] = TF(hsf["length"])
            tfs_map[sw].set_prefix_id("s%d" % sw)
            tfs_map[sw].set_send_on_receiving_port(True)
        return tfs_map

    def save_tfs(tfs_map):
        """ Save a dictionary of transfer functions to various files. """
        global TFS_FOLDER
        for (sw, tf) in tfs_map.iteritems():
            tf.save_object_to_file('%s/s%d.tf' % (TFS_FOLDER, sw))

    ''' Classifier conversion core logic begins here. '''
    tfs_map = init_tfs()
    for sw in sw_ports.keys():
        tf = tfs_map[sw]
        for rule in classifier.rules:
            try:
                mat_map = {} if rule.match == identity else rule.match.map
            except:
                raise RuntimeError("unexpected rule match in classifier!")
            # determine first if this rule applicable to switch sw
            if (('switch' in mat_map and mat_map['switch'] == sw) or
                (not 'switch' in mat_map)):
                mat_wc = get_match_wc(hsf, mat_map)
                in_ports = get_ports(hsf, portids, sw_ports, mat_map, sw)
                (mask, rewrite, outports, rw) = get_action_wc(rule.actions)
                out_ports = process_outports(mat_map, outports, sw, rule)
                rule = TF.create_standard_rule(in_ports, mat_wc, out_ports,
                                               mask, rewrite)
                if rw:
                    tf.add_rewrite_rule(rule)
                else:
                    tf.add_fwd_rule(rule)
    save_tfs(tfs_map)