def _build_group_flood_rules(self, vlan, modify, command):
        """Build flooding rules for a VLAN using groups."""
        _, vlan_flood_acts = self._build_flood_rule_for_vlan(
            vlan, None, None, None, False, command)
        group_id = vlan.vid
        group = self.groups.get_entry(
            group_id, valve_of.build_group_flood_buckets(vlan_flood_acts))
        groups_by_unicast_eth = {False: group, True: group}
        ofmsgs = []

        # Only configure unicast flooding group if has different output
        # actions to non unicast flooding.
        _, unicast_eth_vlan_flood_acts = self._build_flood_rule_for_vlan(
            vlan, None, None, None, True, command)
        unicast_eth_vlan_flood_acts, unicast_output_ports, _ = valve_of.output_non_output_actions(
            unicast_eth_vlan_flood_acts)
        vlan_flood_acts, vlan_output_ports, _ = valve_of.output_non_output_actions(
            vlan_flood_acts)
        if unicast_output_ports != vlan_output_ports:
            group_id += valve_of.VLAN_GROUP_OFFSET
            group = self.groups.get_entry(
                group_id,
                valve_of.build_group_flood_buckets(
                    unicast_eth_vlan_flood_acts))
            groups_by_unicast_eth[True] = group

        for group in groups_by_unicast_eth.values():
            if modify:
                ofmsgs.append(group.modify())
            else:
                ofmsgs.extend(group.add())

        for unicast_eth_dst, eth_type, eth_dst, eth_dst_mask in self.flood_dsts:
            if unicast_eth_dst and not vlan.unicast_flood:
                continue
            group = groups_by_unicast_eth[unicast_eth_dst]
            match = self.flood_table.match(vlan=vlan,
                                           eth_type=eth_type,
                                           eth_dst=eth_dst,
                                           eth_dst_mask=eth_dst_mask)
            flood_priority = self._vlan_flood_priority(eth_type, eth_dst_mask)
            ofmsgs.append(
                self.flood_table.flowmod(
                    match=match,
                    command=command,
                    inst=[
                        valve_of.apply_actions(
                            [valve_of.group_act(group.group_id)])
                    ],
                    priority=flood_priority))
        return ofmsgs
Beispiel #2
0
 def _build_flood_acts_for_port(self, vlan, exclude_unicast, port,  # pylint: disable=too-many-arguments
                                exclude_all_external=False,
                                exclude_restricted_bcast_arpnd=False):
     flood_acts = ()
     port_output_ports = []
     port_non_output_acts = []
     if port.dyn_phys_up:
         if exclude_restricted_bcast_arpnd:
             flood_acts = self._build_flood_rule_actions(
                 vlan, exclude_unicast, port, exclude_all_external, port.restricted_bcast_arpnd)
         else:
             flood_acts = self._build_flood_rule_actions(
                 vlan, exclude_unicast, port, exclude_all_external, False)
         (flood_acts,
          port_output_ports,
          port_non_output_acts) = valve_of.output_non_output_actions(flood_acts)
         if not port_output_ports:
             flood_acts = ()
             port_non_output_acts = ()
     return (flood_acts, port_output_ports, port_non_output_acts)
Beispiel #3
0
 def _build_mask_flood_rules(self, vlan, eth_type, eth_dst, eth_dst_mask,  # pylint: disable=too-many-arguments
                             exclude_unicast, exclude_restricted_bcast_arpnd,
                             command, cold_start):
     ofmsgs = []
     if self.combinatorial_port_flood:
         for port in self._vlan_all_ports(vlan, exclude_unicast):
             flood_acts, _, _ = self._build_flood_acts_for_port(
                 vlan, exclude_unicast, port,
                 exclude_restricted_bcast_arpnd=exclude_restricted_bcast_arpnd)
             if flood_acts:
                 ofmsgs.append(self._build_flood_rule_for_port(
                     vlan, eth_type, eth_dst, eth_dst_mask, command, port, flood_acts))
     else:
         vlan_flood_ofmsg, vlan_flood_acts = self._build_flood_rule_for_vlan(
             vlan, eth_type, eth_dst, eth_dst_mask, exclude_unicast, command)
         if not self.use_group_table:
             ofmsgs.append(vlan_flood_ofmsg)
         (flood_acts,
          vlan_output_ports,
          vlan_non_output_acts) = valve_of.output_non_output_actions(vlan_flood_acts)
         for port in self._vlan_all_ports(vlan, exclude_unicast):
             (flood_acts,
              port_output_ports,
              port_non_output_acts) = self._build_flood_acts_for_port(
                  vlan, exclude_unicast, port,
                  exclude_restricted_bcast_arpnd=exclude_restricted_bcast_arpnd)
             if not flood_acts:
                 continue
             if (vlan_output_ports - set([port.number]) == port_output_ports and
                     vlan_non_output_acts == port_non_output_acts):
                 # Delete a potentially existing port specific flow
                 # TODO: optimize, avoid generating delete for port if no existing flow.
                 if not cold_start:
                     flood_priority, match = self._build_flood_match_priority(
                         port, vlan, eth_type, eth_dst, eth_dst_mask, add_match=None)
                     ofmsgs.append(self.flood_table.flowdel(
                         match=match, priority=flood_priority))
             else:
                 ofmsgs.append(self._build_flood_rule_for_port(
                     vlan, eth_type, eth_dst, eth_dst_mask, command, port, flood_acts))
     return ofmsgs