Example #1
0
def build_output_actions(output_dict):
    """Implement actions to alter packet/output."""
    output_actions = []
    output_port = None
    ofmsgs = []
    # if destination rewriting selected, rewrite it.
    if 'dl_dst' in output_dict:
        output_actions.append(valve_of.set_eth_dst(output_dict['dl_dst']))
    # rewrite any VLAN headers.
    vlan_actions = rewrite_vlan(output_dict)
    if vlan_actions:
        output_actions.extend(vlan_actions)
    if 'port' in output_dict:
        output_port = output_dict['port']
        output_actions.append(valve_of.output_port(output_port))
    if 'failover' in output_dict:
        failover = output_dict['failover']
        group_id = failover['group_id']
        buckets = []
        for port in failover['ports']:
            buckets.append(
                valve_of.bucket(watch_port=port,
                                actions=[valve_of.output_port(port)]))
        ofmsgs.append(valve_of.groupdel(group_id=group_id))
        ofmsgs.append(valve_of.groupadd_ff(group_id=group_id, buckets=buckets))
        output_actions.append(valve_of.group_act(group_id=group_id))
    return (output_port, output_actions, ofmsgs)
Example #2
0
def build_acl_entry(rule_conf, acl_allow_inst, port_num=None, vlan_vid=None):
    acl_inst = []
    match_dict = {}
    for attrib, attrib_value in list(rule_conf.items()):
        if attrib.startswith('_') and attrib.endswith('_'):
            continue
        if attrib == 'in_port':
            continue
        if attrib == 'actions':
            allow = False
            allow_specified = False
            if 'allow' in attrib_value:
                allow_specified = True
                if attrib_value['allow'] == 1:
                    allow = True
            if 'mirror' in attrib_value:
                port_no = attrib_value['mirror']
                acl_inst.append(
                    valve_of.apply_actions([valve_of.output_port(port_no)]))
                if not allow_specified:
                    allow = True
            if 'output' in attrib_value:
                output_dict = attrib_value['output']
                output_actions = []
                output_port = None
                if 'port' in output_dict:
                    output_port = output_dict['port']

                # if destination rewriting selected, rewrite it.
                if 'dl_dst' in output_dict:
                    output_actions.append(
                        valve_of.set_eth_dst(output_dict['dl_dst']))
                # rewrite any VLAN headers.
                vlan_actions = rewrite_vlan(output_dict)
                if vlan_actions:
                    output_actions.extend(vlan_actions)
                # output to a port if specified.
                if output_port is not None:
                    output_actions.append(valve_of.output_port(output_port))

                acl_inst.append(valve_of.apply_actions(output_actions))

                # if port specified, output packet now and exit pipeline.
                if output_port is not None:
                    continue

            if allow:
                acl_inst.append(acl_allow_inst)
        else:
            match_dict[attrib] = attrib_value
    if port_num is not None:
        match_dict['in_port'] = port_num
    if vlan_vid is not None:
        match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    acl_match = valve_of.match_from_dict(match_dict)
    return acl_match, acl_inst
Example #3
0
    def build_port_out_inst(self, vlan, port):
        dst_act = []
        if not vlan.port_is_tagged(port) and port.stack is None:
            dst_act.append(valve_of.pop_vlan())
        dst_act.append(valve_of.output_port(port.number))

        if port.mirror is not None:
            mirror_acts = [valve_of.output_port(port.mirror)]
            dst_act.extend(mirror_acts)

        return [valve_of.apply_actions(dst_act)]
Example #4
0
 def _build_group_buckets(self, vlan, unicast_flood):
     buckets = []
     for port in vlan.tagged_flood_ports(unicast_flood):
         buckets.append(valve_of.bucket(
             actions=[valve_of.output_port(port.number)]))
     for port in vlan.untagged_flood_ports(unicast_flood):
         buckets.append(valve_of.bucket(
             actions=[
                 valve_of.pop_vlan(),
                 valve_of.output_port(port.number)]))
     return buckets
Example #5
0
    def build_port_out_inst(self, vlan, port):
        dst_act = []
        if not vlan.port_is_tagged(port.number) and port.stack is None:
            dst_act.append(valve_of.pop_vlan())
        dst_act.append(valve_of.output_port(port.number))

        if port.mirror is not None:
            mirror_acts = [valve_of.output_port(port.mirror)]
            dst_act.extend(mirror_acts)

        return [valve_of.apply_actions(dst_act)]
Example #6
0
 def _build_group_buckets(self, vlan, unicast_flood):
     buckets = []
     for port in vlan.tagged_flood_ports(unicast_flood):
         buckets.append(valve_of.bucket(
             actions=[valve_of.output_port(port.number)]))
     for port in vlan.untagged_flood_ports(unicast_flood):
         buckets.append(valve_of.bucket(
             actions=[
                 valve_of.pop_vlan(),
                 valve_of.output_port(port.number)]))
     return buckets
Example #7
0
 def _build_flood_rule_actions(self, vlan, exclude_unicast, exclude_ports=[]):
     flood_acts = []
     tagged_ports = vlan.tagged_flood_ports(exclude_unicast)
     untagged_ports = vlan.untagged_flood_ports(exclude_unicast)
     for port in tagged_ports:
         if port not in exclude_ports:
             flood_acts.append(valve_of.output_port(port.number))
     if untagged_ports:
         flood_acts.append(valve_of.pop_vlan())
         for port in untagged_ports:
             if port not in exclude_ports:
                 flood_acts.append(valve_of.output_port(port.number))
     return flood_acts
Example #8
0
 def _nexthop_group_buckets(self, vlan, in_port, eth_src):
     actions = self._nexthop_actions(eth_src)
     if not vlan.port_is_tagged(in_port):
         actions.append(valve_of.pop_vlan())
     actions.append(valve_of.output_port(in_port))
     buckets = [valve_of.bucket(actions=actions)]
     return buckets
Example #9
0
 def _build_flood_port_outputs(self, ports, exclude_port):
     flood_acts = []
     for port in ports:
         if port == exclude_port:
             continue
         flood_acts.append(valve_of.output_port(port.number))
     return flood_acts
Example #10
0
 def _build_flood_port_outputs(self, ports, exclude_port):
     flood_acts = []
     for port in ports:
         if port == exclude_port:
             continue
         flood_acts.append(valve_of.output_port(port.number))
     return flood_acts
Example #11
0
 def _nexthop_group_buckets(self, vlan, in_port, eth_src):
     actions = self._nexthop_actions(eth_src)
     if not vlan.port_is_tagged(in_port):
         actions.append(valve_of.pop_vlan())
     actions.append(valve_of.output_port(in_port))
     buckets = [valve_of.bucket(actions=actions)]
     return buckets
Example #12
0
 def build_flood_rules(self, vlan, modify=False):
     """Add flows to flood packets to unknown destinations on a VLAN."""
     # TODO: not all vendors implement groups well.
     # That means we need flood rules for each input port, outputting
     # to all ports except the input port. When all vendors implement
     # groups correctly we can use them.
     command = ofp.OFPFC_ADD
     if modify:
         command = ofp.OFPFC_MODIFY_STRICT
     flood_priority = self.flood_priority
     flood_eth_dst_matches = []
     if vlan.unicast_flood:
         flood_eth_dst_matches.extend([(None, None)])
     flood_eth_dst_matches.extend([
         ('01:80:C2:00:00:00', 'ff:ff:ff:00:00:00'), # 802.x
         ('01:00:5E:00:00:00', 'ff:ff:ff:00:00:00'), # IPv4 multicast
         ('33:33:00:00:00:00', 'ff:ff:00:00:00:00'), # IPv6 multicast
         (mac.BROADCAST_STR, None), # flood on ethernet broadcasts
     ])
     ofmsgs = []
     vlan_all_ports = vlan.flood_ports(vlan.get_ports(), False)
     mirrored_ports = vlan.mirrored_ports()
     for eth_dst, eth_dst_mask in flood_eth_dst_matches:
         for port in vlan_all_ports:
             if eth_dst is None:
                 flood_acts = self._build_flood_rule_actions(
                     vlan, False, exclude_ports=[port])
             else:
                 flood_acts = self._build_flood_rule_actions(
                     vlan, True, exclude_ports=[port])
             ofmsgs.append(self.valve_flowmod(
                 self.flood_table,
                 match=self.valve_in_match(
                     self.flood_table, in_port=port.number, vlan=vlan,
                     eth_dst=eth_dst, eth_dst_mask=eth_dst_mask),
                 command=command,
                 inst=[valve_of.apply_actions(flood_acts)],
                 priority=flood_priority))
         flood_priority += 1
         for port in mirrored_ports:
             if eth_dst is None:
                 flood_acts = self._build_flood_rule_actions(vlan, False)
             else:
                 flood_acts = self._build_flood_rule_actions(vlan, True)
             mirror_acts = [
                 valve_of.output_port(port.mirror)] + flood_acts
             ofmsgs.append(self.valve_flowmod(
                 self.flood_table,
                 match=self.valve_in_match(
                     self.flood_table,
                     vlan=vlan,
                     in_port=port.number,
                     eth_dst=eth_dst,
                     eth_dst_mask=eth_dst_mask),
                 command=command,
                 inst=[valve_of.apply_actions(mirror_acts)],
                 priority=flood_priority))
         flood_priority += 1
     return ofmsgs
Example #13
0
def build_acl_entry(rule_conf, acl_allow_inst, port_num=None, vlan_vid=None):
    acl_inst = []
    match_dict = {}
    for attrib, attrib_value in rule_conf.items():
        if attrib == 'in_port':
            continue
        if attrib == 'actions':
            allow = False
            allow_specified = False
            if 'allow' in attrib_value:
                allow_specified = True
                if attrib_value['allow'] == 1:
                    allow = True
            if 'mirror' in attrib_value:
                port_no = attrib_value['mirror']
                acl_inst.append(
                    valve_of.apply_actions([valve_of.output_port(port_no)]))
                if not allow_specified:
                    allow = True
            # if output selected, output packet now and exit pipeline.
            if 'output' in attrib_value:
                output_dict = attrib_value['output']
                output_actions = []
                # if destination rewriting selected, rewrite it.
                if 'dl_dst' in output_dict:
                    output_actions.append(
                        valve_of.set_eth_dst(output_dict['dl_dst']))
                # if vlan tag is specified, push it.
                if 'vlan_vid' in output_dict:
                    output_actions.extend(
                        valve_of.push_vlan_act(output_dict['vlan_vid']))
                # output to port
                port_no = output_dict['port']
                output_actions.append(valve_of.output_port(port_no))
                acl_inst.append(valve_of.apply_actions(output_actions))
                continue
            if allow:
                acl_inst.append(acl_allow_inst)
        else:
            match_dict[attrib] = attrib_value
    if port_num is not None:
        match_dict['in_port'] = port_num
    if vlan_vid is not None:
        match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    acl_match = valve_of.match_from_dict(match_dict)
    return acl_match, acl_inst
Example #14
0
def build_acl_entry(rule_conf, acl_allow_inst, port_num=None, vlan_vid=None):
    acl_inst = []
    match_dict = {}
    for attrib, attrib_value in rule_conf.iteritems():
        if attrib == 'in_port':
            continue
        if attrib == 'actions':
            allow = False
            allow_specified = False
            if 'allow' in attrib_value:
                allow_specified = True
                if attrib_value['allow'] == 1:
                    allow = True
            if 'mirror' in attrib_value:
                port_no = attrib_value['mirror']
                acl_inst.append(
                    valve_of.apply_actions([valve_of.output_port(port_no)]))
                if not allow_specified:
                    allow = True
            # if output selected, output packet now and exit pipeline.
            if 'output' in attrib_value:
                output_dict = attrib_value['output']
                output_actions = []
                # if destination rewriting selected, rewrite it.
                if 'dl_dst' in output_dict:
                    output_actions.append(
                        valve_of.set_eth_dst(output_dict['dl_dst']))
                # if vlan tag is specified, push it.
                if 'vlan_vid' in output_dict:
                    output_actions.extend(
                        valve_of.push_vlan_act(output_dict['vlan_vid']))
                # output to port
                port_no = output_dict['port']
                output_actions.append(valve_of.output_port(port_no))
                acl_inst.append(valve_of.apply_actions(output_actions))
                continue
            if allow:
                acl_inst.append(acl_allow_inst)
        else:
            match_dict[attrib] = attrib_value
    if port_num is not None:
        match_dict['in_port'] = port_num
    if vlan_vid is not None:
        match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    acl_match = valve_of.match_from_dict(match_dict)
    return acl_match, acl_inst
Example #15
0
 def _build_flood_port_outputs(self, ports, in_port):
     flood_acts = []
     for port in ports:
         if port == in_port:
             if port.hairpin:
                 flood_acts.append(valve_of.output_in_port())
         else:
             flood_acts.append(valve_of.output_port(port.number))
     return flood_acts
Example #16
0
 def _build_mirrored_flood_rules(self, vlan, eth_dst, eth_dst_mask,
                                 exclude_unicast, command, flood_priority):
     ofmsgs = []
     mirrored_ports = vlan.mirrored_ports()
     for port in mirrored_ports:
         mirror_acts = [valve_of.output_port(port.mirror)]
         ofmsgs.extend(self._build_flood_rule_for_port(
             vlan, eth_dst, eth_dst_mask,
             exclude_unicast, command, flood_priority,
             port, mirror_acts))
     return ofmsgs
Example #17
0
 def _build_mirrored_flood_rules(self, vlan, eth_dst, eth_dst_mask,
                                 exclude_unicast, command, flood_priority):
     ofmsgs = []
     mirrored_ports = vlan.mirrored_ports()
     for port in mirrored_ports:
         mirror_acts = [valve_of.output_port(port.mirror)]
         ofmsgs.extend(self._build_flood_rule_for_port(
             vlan, eth_dst, eth_dst_mask,
             exclude_unicast, command, flood_priority,
             port, mirror_acts))
     return ofmsgs
Example #18
0
    def port_add(self, dp_id, port_num):
        """Handle the addition of a port.

        Args:
            dp_id (int): datapath ID.
            port_num (int): port number.
        Returns:
            list: OpenFlow messages, if any.
        """
        if self._ignore_dpid(dp_id) or valve_of.ignore_port(port_num):
            return []

        if port_num not in self.dp.ports:
            self.logger.info(
                'Ignoring port:%u not present in configuration file', port_num)
            return []

        port = self.dp.ports[port_num]
        self.logger.info('Port %s added', port)
        port.phys_up = True

        if not port.running():
            return []

        ofmsgs = []
        self.logger.info('Sending config for port %s', port)

        # Delete all flows previously matching this port
        ofmsgs.extend(self._delete_all_port_match_flows(port))

        # Port is a mirror destination; drop all input packets
        if port.mirror_destination:
            ofmsgs.append(self.valve_flowdrop(
                self.dp.vlan_table,
                match=self.valve_in_match(self.dp.vlan_table, in_port=port_num),
                priority=self.dp.highest_priority))
            return ofmsgs

        # Add ACL if any
        acl_ofmsgs, forwarding_table = self._port_add_acl(port_num)
        ofmsgs.extend(acl_ofmsgs)

        # Add mirroring if any
        mirror_act = []
        if port.mirror:
            mirror_act = [valve_of.output_port(port.mirror)]

        # Add port/to VLAN rules.
        ofmsgs.extend(self._port_add_vlans(port, forwarding_table, mirror_act))

        return ofmsgs
Example #19
0
def build_acl_entry(rule_conf,
                    acl_allow_inst,
                    meters,
                    port_num=None,
                    vlan_vid=None):
    acl_inst = []
    match_dict = {}
    ofmsgs = []
    for attrib, attrib_value in list(rule_conf.items()):
        if attrib == 'in_port':
            continue
        if attrib == 'actions':
            allow = False
            allow_specified = False
            if 'allow' in attrib_value:
                allow_specified = True
                if attrib_value['allow'] == 1:
                    allow = True
            if 'meter' in attrib_value:
                meter_name = attrib_value['meter']
                acl_inst.append(
                    valve_of.apply_meter(meters[meter_name].meter_id))
            if 'mirror' in attrib_value:
                port_no = attrib_value['mirror']
                acl_inst.append(
                    valve_of.apply_actions([valve_of.output_port(port_no)]))
                if not allow_specified:
                    allow = True
            if 'output' in attrib_value:
                output_port, output_actions, output_ofmsgs = build_output_actions(
                    attrib_value['output'])
                acl_inst.append(valve_of.apply_actions(output_actions))
                ofmsgs.extend(output_ofmsgs)

                # if port specified, output packet now and exit pipeline.
                if output_port is not None:
                    continue

            if allow:
                acl_inst.append(acl_allow_inst)
        else:
            match_dict[attrib] = attrib_value
    if port_num is not None:
        match_dict['in_port'] = port_num
    if vlan_vid is not None:
        match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    acl_match = valve_of.match_from_dict(match_dict)
    return (acl_match, acl_inst, ofmsgs)
Example #20
0
    def _update_nexthop(self, vlan, in_port, eth_src, resolved_ip_gw):
        ofmsgs = []
        is_updated = None
        routes = self._vlan_routes(vlan)
        group_mod_method = None
        group_id = None

        nexthop_cache_entry = self._vlan_nexthop_cache_entry(
            vlan, resolved_ip_gw)
        if (nexthop_cache_entry is not None and
                nexthop_cache_entry.eth_src is not None):
            cached_eth_dst = nexthop_cache_entry.eth_src
            if cached_eth_dst != eth_src:
                is_updated = True
                if self.use_group_table:
                    group_mod_method = valve_of.groupmod
                    group_id = self.ip_gw_to_group_id[resolved_ip_gw]
        else:
            is_updated = False
            if self.use_group_table:
                group_mod_method = valve_of.groupadd
                group_id = self._group_id_from_ip_gw(resolved_ip_gw)
                self.ip_gw_to_group_id[resolved_ip_gw] = group_id

        if is_updated is not None:
            if self.use_group_table:
                actions = []
                actions.extend([
                    valve_of.set_eth_src(self.faucet_mac),
                    valve_of.set_eth_dst(eth_src),
                    valve_of.dec_ip_ttl()])
                if not vlan.port_is_tagged(in_port):
                    actions.append(valve_of.pop_vlan())
                actions.append(valve_of.output_port(in_port))
                ofmsgs.append(group_mod_method(
                    group_id=group_id,
                    buckets=[valve_of.bucket(actions=actions)]))

            for ip_dst, ip_gw in routes.iteritems():
                if ip_gw == resolved_ip_gw:
                    ofmsgs.extend(self._add_resolved_route(
                        vlan, ip_gw, ip_dst, eth_src, is_updated))

        self._update_nexthop_cache(vlan, eth_src, resolved_ip_gw)
        return ofmsgs
Example #21
0
    def port_add(self, dp_id, port_num, modify=False):
        """Handle the addition of a port.

        Args:
            dp_id (int): datapath ID.
            port_num (int): port number.
        Returns:
            list: OpenFlow messages, if any.
        """
        if self._ignore_dpid(dp_id) or valve_of.ignore_port(port_num):
            return []

        if port_num not in self.dp.ports:
            self.logger.info(
                'Ignoring port:%u not present in configuration file', port_num)
            return []

        port = self.dp.ports[port_num]
        port.phys_up = True

        ofmsgs = []
        if modify:
            # delete all rules related to this port
            tables = [self.dp.vlan_table, self.dp.acl_table,
                      self.dp.eth_src_table, self.dp.flood_table]
            for table_id in tables:
                ofmsgs.extend(self.valve_flowdel(
                    table_id,
                    self.valve_in_match(table_id, in_port=port_num)))

            if not port.permanent_learn:
                # delete eth_dst rules
                ofmsgs.extend(self.valve_flowdel(
                    self.dp.eth_dst_table,
                    out_port=port_num))
            self.logger.info('Port %s modified', port)
        else:
            self.logger.info('Port %s added', port)

        if not port.running():
            return ofmsgs

        self.logger.info('Sending config for port %s', port)

        # Delete all flows previously matching this port
        ofmsgs.extend(self._delete_all_port_match_flows(port))

        # Port is a mirror destination; drop all input packets
        if port.mirror_destination:
            ofmsgs.append(self.valve_flowdrop(
                self.dp.vlan_table,
                match=self.valve_in_match(self.dp.vlan_table, in_port=port_num),
                priority=self.dp.highest_priority))
            return ofmsgs

        # Add ACL if any.
        acl_ofmsgs, forwarding_table = self._port_add_acl(port_num)
        ofmsgs.extend(acl_ofmsgs)

        # If this is a stacking port, accept all VLANs (came from another FAUCET)
        if port.stack is not None:
            ofmsgs.append(self.valve_flowmod(
                self.dp.vlan_table,
                match=self.valve_in_match(self.dp.vlan_table, in_port=port_num),
                priority=self.dp.low_priority,
                inst=[valve_of.goto_table(forwarding_table)]))
            return ofmsgs

        # Add mirroring if any
        mirror_act = []
        if port.mirror:
            mirror_act = [valve_of.output_port(port.mirror)]

        # Add port/to VLAN rules.
        ofmsgs.extend(self._port_add_vlans(port, forwarding_table, mirror_act))

        return ofmsgs
Example #22
0
    def port_add(self, dp_id, port_num, modify=False):
        """Handle the addition of a port.

        Args:
            dp_id (int): datapath ID.
            port_num (int): port number.
        Returns:
            list: OpenFlow messages, if any.
        """
        if self._ignore_dpid(dp_id) or valve_of.ignore_port(port_num):
            return []

        if port_num not in self.dp.ports:
            self.logger.info(
                'Ignoring port:%u not present in configuration file', port_num)
            return []

        port = self.dp.ports[port_num]
        port.phys_up = True

        ofmsgs = []
        if modify:
            if not port.permanent_learn:
                # delete eth_dst rules
                ofmsgs.extend(self.valve_flowdel(
                    self.dp.eth_dst_table,
                    out_port=port_num))
            self.logger.info('Port %s modified', port)
        else:
            self.logger.info('Port %s added', port)

        if not port.running():
            return ofmsgs

        self.logger.info('Sending config for port %s', port)

        # Delete all flows previously matching this port
        ofmsgs.extend(self._delete_all_port_match_flows(port))

        # Port is a mirror destination; drop all input packets
        if port.mirror_destination:
            ofmsgs.append(self.valve_flowdrop(
                self.dp.vlan_table,
                match=self.valve_in_match(self.dp.vlan_table, in_port=port_num),
                priority=self.dp.highest_priority))
            return ofmsgs

        # Add ACL if any.
        acl_ofmsgs = self._port_add_acl(port_num)
        ofmsgs.extend(acl_ofmsgs)

        # If this is a stacking port, accept all VLANs (came from another FAUCET)
        if port.stack is not None:
            ofmsgs.append(self.valve_flowmod(
                self.dp.vlan_table,
                match=self.valve_in_match(self.dp.vlan_table, in_port=port_num),
                priority=self.dp.low_priority,
                inst=[valve_of.goto_table(self.dp.eth_src_table)]))
            for vlan in self.dp.vlans.values():
                ofmsgs.extend(self.flood_manager.build_flood_rules(vlan))
        else:
            mirror_act = []
            # Add mirroring if any
            if port.mirror:
                mirror_act = [valve_of.output_port(port.mirror)]
            # Add port/to VLAN rules.
            ofmsgs.extend(self._port_add_vlans(port, mirror_act))
        return ofmsgs