Example #1
0
 def create_dot1x_flow_pair(self, dot1x_port, nfv_sw_port, mac):
     ofmsgs = [
         self.port_acl_table.flowmod(
             match=self.port_acl_table.match(
                 in_port=dot1x_port.number,
                 eth_type=valve_packet.ETH_EAPOL),
             priority=self.acl_priority,
             inst=[
                 valve_of.apply_actions([
                     self.port_acl_table.set_field(eth_dst=mac),
                     valve_of.output_port(nfv_sw_port.number)
                 ])
             ],
         ),
         self.port_acl_table.flowmod(
             match=self.port_acl_table.match(
                 in_port=nfv_sw_port.number,
                 eth_type=valve_packet.ETH_EAPOL,
                 eth_src=mac),
             priority=self.acl_priority,
             inst=[
                 valve_of.apply_actions([
                     self.port_acl_table.set_field(
                         eth_src=valve_packet.EAPOL_ETH_DST),
                     valve_of.output_port(dot1x_port.number)
                 ])
             ],
         )
     ]
     return ofmsgs
Example #2
0
 def create_dot1x_flow_pair(self, dot1x_port, nfv_sw_port, mac):
     ofmsgs = [
         self.port_acl_table.flowmod(
             match=self.port_acl_table.match(
                 in_port=dot1x_port.number,
                 eth_type=valve_packet.ETH_EAPOL),
             priority=self.acl_priority,
             inst=[valve_of.apply_actions([
                 self.port_acl_table.set_field(eth_dst=mac),
                 valve_of.output_port(nfv_sw_port.number)])],
             ),
         self.port_acl_table.flowmod(
             match=self.port_acl_table.match(
                 in_port=nfv_sw_port.number,
                 eth_type=valve_packet.ETH_EAPOL,
                 eth_src=mac),
             priority=self.acl_priority,
             inst=[valve_of.apply_actions([
                 self.port_acl_table.set_field(
                     eth_src=valve_packet.EAPOL_ETH_DST),
                 valve_of.output_port(dot1x_port.number)
                 ])],
             )
         ]
     return ofmsgs
Example #3
0
 def create_dot1x_flow_pair(self, port_num, nfv_sw_port_num, mac):
     """Create dot1x flow pair"""
     ofmsgs = [
         self.port_acl_table.flowmod(
             match=self.port_acl_table.match(
                 in_port=port_num,
                 eth_type=valve_packet.ETH_EAPOL),
             priority=self.dot1x_static_rules_priority,
             inst=[valve_of.apply_actions([
                 self.port_acl_table.set_field(eth_dst=mac),
                 valve_of.output_port(nfv_sw_port_num)])],
         ),
         self.port_acl_table.flowmod(
             match=self.port_acl_table.match(
                 in_port=nfv_sw_port_num,
                 eth_type=valve_packet.ETH_EAPOL,
                 eth_src=mac),
             priority=self.dot1x_static_rules_priority,
             inst=[valve_of.apply_actions([
                 self.port_acl_table.set_field(
                     eth_src=valve_packet.EAPOL_ETH_DST),
                 valve_of.output_port(port_num)
             ])],
         )
     ]
     return ofmsgs
Example #4
0
 def _add_resolved_route(self, vlan, ip_gw, ip_dst, eth_dst, is_updated):
     ofmsgs = []
     if is_updated:
         self.logger.info(
             'Updating next hop for route %s via %s (%s) on VLAN %u' %
             (ip_dst, ip_gw, eth_dst, vlan.vid))
         ofmsgs.extend(self._del_route_flows(vlan, ip_dst))
     else:
         self.logger.info('Adding new route %s via %s (%s) on VLAN %u' %
                          (ip_dst, ip_gw, eth_dst, vlan.vid))
     if self.use_group_table:
         inst = [
             valve_of.apply_actions([
                 valve_of.group_act(
                     group_id=self._group_id_from_ip_gw(vlan, ip_gw))
             ])
         ]
     else:
         inst = [
             valve_of.apply_actions(self._nexthop_actions(eth_dst, vlan)),
             valve_of.goto_table(self.eth_dst_table)
         ]
     for routed_vlan in self._routed_vlans(vlan):
         in_match = self._route_match(routed_vlan, ip_dst)
         ofmsgs.append(
             self.fib_table.flowmod(in_match,
                                    priority=self._route_priority(ip_dst),
                                    inst=inst))
     return ofmsgs
Example #5
0
    def get_port_acls(self, valve, dot1x_port):
        """Setup the dot1x forward port acls.
        Args:
            dot1x_port:
            valve:

        Returns:
            list of flowmods
        """
        port_acl_table = valve.dp.tables['port_acl']
        nfv_sw_port = valve.dp.dot1x['nfv_sw_port']
        valve_index = self.dp_id_to_valve_index[valve.dp.dp_id]
        mac = get_mac_str(valve_index, dot1x_port.number)
        ofmsgs = []
        ofmsgs.append(port_acl_table.flowmod(
            port_acl_table.match(
                in_port=dot1x_port.number,
                eth_type=valve_packet.ETH_EAPOL),
            priority=valve.dp.highest_priority,
            inst=[valve_of.apply_actions([
                valve_of.set_field(eth_dst=mac),
                valve_of.output_port(nfv_sw_port)])]))
        ofmsgs.append(port_acl_table.flowmod(
            port_acl_table.match(
                in_port=nfv_sw_port,
                eth_type=valve_packet.ETH_EAPOL,
                eth_src=mac),
            priority=valve.dp.highest_priority,
            inst=[valve_of.apply_actions([
                valve_of.set_field(eth_src=EAPOL_DST),
                valve_of.output_port(dot1x_port.number)])]))
        return ofmsgs
Example #6
0
    def create_flow_pair(self, dot1x_port, nfv_sw_port, valve):
        """Creates the pair of flows that redirects the eapol packets to/from the supplicant and
        nfv port

        Args:
            dot1x_port (Port):
            nfv_sw_port (int):
            valve (Valve):

        Returns:
            list
        """
        port_acl_table = valve.dp.tables['port_acl']
        valve_index = self.dp_id_to_valve_index[valve.dp.dp_id]
        mac = get_mac_str(valve_index, dot1x_port.number)

        if dot1x_port.running():
            return [
                port_acl_table.flowmod(
                    inst=[valve_of.apply_actions([
                        valve_of.set_field(eth_dst=mac),
                        valve_of.output_port(nfv_sw_port)])],
                    **FaucetDot1x.get_dot1x_port_match_priority(dot1x_port, port_acl_table, valve)),
                port_acl_table.flowmod(
                    inst=[valve_of.apply_actions([
                        valve_of.set_field(eth_src=EAPOL_DST),
                        valve_of.output_port(dot1x_port.number)])],
                    **FaucetDot1x.get_nfv_sw_port_match_priority(mac, nfv_sw_port,
                                                                 port_acl_table, valve)
                )]
        return []
Example #7
0
    def create_dot1x_flow_pair(self, port_num, nfv_sw_port_num, mac):
        """Create dot1x flow pair"""
        ofmsgs = [
            self.port_acl_table.flowmod(
                match=self.port_acl_table.match(
                    in_port=port_num,
                    eth_type=valve_packet.ETH_EAPOL),
                priority=self.override_priority,
                inst=(valve_of.apply_actions([
                    self.port_acl_table.set_field(eth_dst=mac),
                    valve_of.output_port(nfv_sw_port_num)]),),
            ),
            self.port_acl_table.flowmod(
                match=self.port_acl_table.match(
                    in_port=nfv_sw_port_num,
                    eth_type=valve_packet.ETH_EAPOL,
                    eth_src=mac),
                priority=self.override_priority,
                inst=(valve_of.apply_actions([
                    self.port_acl_table.set_field(
                        eth_src=valve_packet.EAPOL_ETH_DST),
                    valve_of.output_port(port_num)
                ]),),
            )
        ]

        return ofmsgs
Example #8
0
    def learn_host_on_vlan_port_flows(self, port, vlan, eth_src,
                                      delete_existing, src_rule_idle_timeout,
                                      src_rule_hard_timeout,
                                      dst_rule_idle_timeout):
        """Return flows that implement learning a host on a port."""
        ofmsgs = []

        if port.permanent_learn:
            # Antispoofing rule for this MAC.
            ofmsgs.append(
                self.eth_src_table.flowdrop(self.eth_src_table.match(
                    vlan=vlan, eth_src=eth_src),
                                            priority=(self.host_priority - 2)))
        else:
            # Delete any existing entries for MAC.
            # TODO: for LAGs, don't delete entries in the same LAG.
            if delete_existing:
                ofmsgs.extend(self.delete_host_from_vlan(eth_src, vlan))

        # Associate this MAC with source port.
        ofmsgs.append(
            self.eth_src_table.flowmod(
                self.eth_src_table.match(in_port=port.number,
                                         vlan=vlan,
                                         eth_src=eth_src),
                priority=(self.host_priority - 1),
                inst=[valve_of.goto_table(self.eth_dst_table)],
                hard_timeout=src_rule_hard_timeout,
                idle_timeout=src_rule_idle_timeout))

        # Output packets for this MAC to specified port.
        ofmsgs.append(
            self.eth_dst_table.flowmod(
                self.eth_dst_table.match(vlan=vlan, eth_dst=eth_src),
                priority=self.host_priority,
                inst=[valve_of.apply_actions(vlan.output_port(port))],
                idle_timeout=dst_rule_idle_timeout))

        # If port is in hairpin mode, install a special rule
        # that outputs packets destined to this MAC back out the same
        # port they came in (e.g. multiple hosts on same WiFi AP,
        # and FAUCET is switching between them on the same port).
        if port.hairpin:
            ofmsgs.append(
                self.eth_dst_table.flowmod(
                    self.eth_dst_table.match(in_port=port.number,
                                             vlan=vlan,
                                             eth_dst=eth_src),
                    priority=(self.host_priority + 1),
                    inst=[
                        valve_of.apply_actions(
                            vlan.output_port(port, hairpin=True))
                    ],
                    idle_timeout=dst_rule_idle_timeout))

        return ofmsgs
Example #9
0
def build_acl_entry(rule_conf,
                    acl_allow_inst,
                    meters,
                    port_num=None,
                    vlan_vid=None):
    acl_inst = []
    acl_match_dict = {}
    acl_ofmsgs = []
    acl_cookie = None
    for attrib, attrib_value in list(rule_conf.items()):
        if attrib == 'in_port':
            continue
        if attrib == 'cookie':
            acl_cookie = attrib_value
            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))
                acl_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:
            acl_match_dict[attrib] = attrib_value
    if port_num is not None:
        acl_match_dict['in_port'] = port_num
    if vlan_vid is not None:
        acl_match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    try:
        acl_match = valve_of.match_from_dict(acl_match_dict)
    except TypeError:
        assert False, 'invalid type in ACL'
    return (acl_match, acl_inst, acl_cookie, acl_ofmsgs)
Example #10
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 == '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 #11
0
 def add_faucet_vip(self, vlan, faucet_vip):
     ofmsgs = []
     max_prefixlen = faucet_vip.ip.max_prefixlen
     faucet_vip_host = self._host_from_faucet_vip(faucet_vip)
     priority = self.route_priority + max_prefixlen
     faucet_vip_host_nd_mcast = valve_packet.ipv6_link_eth_mcast(
         valve_packet.ipv6_solicited_node_from_ucast(faucet_vip.ip))
     ofmsgs.append(self.valve_flowmod(
         self.eth_src_table,
         self.valve_in_match(
             self.eth_src_table,
             eth_type=self._eth_type(),
             vlan=vlan,
             nw_proto=inet.IPPROTO_ICMPV6,
             eth_dst=faucet_vip_host_nd_mcast,
             icmpv6_type=icmpv6.ND_NEIGHBOR_SOLICIT),
         priority=priority,
         inst=[
             valve_of.apply_actions([valve_of.output_controller()]),
             valve_of.goto_table(self.flood_table)]))
     ofmsgs.append(self.valve_flowmod(
         self.eth_src_table,
         self.valve_in_match(
             self.eth_src_table,
             eth_type=self._eth_type(),
             eth_dst=self.faucet_mac,
             vlan=vlan,
             nw_proto=inet.IPPROTO_ICMPV6,
             icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT),
         priority=priority,
         inst=[valve_of.apply_actions([valve_of.output_controller()])]))
     # Initialize IPv6 FIB
     ofmsgs.append(self.valve_flowmod(
         self.eth_src_table,
         self.valve_in_match(
             self.eth_src_table,
             eth_type=self._eth_type(),
             eth_dst=self.faucet_mac,
             vlan=vlan),
         priority=self.route_priority,
         inst=[valve_of.goto_table(self.fib_table)]))
     ofmsgs.append(self.valve_flowcontroller(
         self.fib_table,
         self.valve_in_match(
             self.fib_table,
             eth_type=self._eth_type(),
             vlan=vlan,
             nw_proto=inet.IPPROTO_ICMPV6,
             nw_dst=faucet_vip_host,
             icmpv6_type=icmpv6.ICMPV6_ECHO_REQUEST),
         priority=priority))
     return ofmsgs
Example #12
0
def build_tunnel_ofmsgs(rule_conf,
                        acl_table,
                        priority,
                        port_num=None,
                        vlan_vid=None,
                        flowdel=False):
    """Build a specific tunnel only ofmsgs"""
    ofmsgs = []
    acl_inst = []
    acl_match = []
    acl_match_dict = {}
    _, output_actions, output_ofmsgs = build_output_actions(
        acl_table, rule_conf)
    ofmsgs.extend(output_ofmsgs)
    acl_inst.append(valve_of.apply_actions(output_actions))
    if port_num is not None:
        acl_match_dict['in_port'] = port_num
    if vlan_vid is not None:
        acl_match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    acl_match = valve_of.match_from_dict(acl_match_dict)
    flowmod = acl_table.flowmod(acl_match, priority=priority, inst=acl_inst)
    if flowdel:
        ofmsgs.append(
            acl_table.flowdel(match=acl_match, priority=priority,
                              strict=False))
    ofmsgs.append(flowmod)
    return ofmsgs
Example #13
0
 def _port_add_vlan_tagged(self, port, vlan, forwarding_table, mirror_act):
     vlan_inst = [
         valve_of.goto_table(forwarding_table)
     ]
     if mirror_act:
         vlan_inst = [valve_of.apply_actions(mirror_act)] + vlan_inst
     return self._port_add_vlan_rules(port, vlan, vlan_inst)
Example #14
0
 def add_port(self, port):
     """Add flows to allow coprocessor to inject or output packets."""
     ofmsgs = []
     if port.coprocessor:
         ofmsgs.append(
             self.vlan_table.flowmod(
                 self.vlan_table.match(in_port=port.number),
                 priority=self.low_priority,
                 inst=(self.vlan_table.goto(self.copro_table), )))
         ofmsgs.append(
             self.eth_src_table.flowmod(
                 match=self.eth_src_table.match(in_port=port.number),
                 priority=self.high_priority,
                 inst=(self.eth_src_table.goto(self.output_table), )))
         # TODO: add additional output port strategies (eg. MPLS) and tagged ports
         vlan_vid_base = port.coprocessor.get('vlan_vid_base', 0)
         for port_number in self.ports:
             inst = (valve_of.apply_actions(
                 (valve_of.pop_vlan(),
                  valve_of.output_port(port_number))), )
             vid = vlan_vid_base + port_number
             vlan = OFVLAN(str(vid), vid)
             match = self.copro_table.match(vlan=vlan)
             ofmsgs.append(
                 self.copro_table.flowmod(match=match,
                                          priority=self.high_priority,
                                          inst=inst))
     return ofmsgs
Example #15
0
 def _add_faucet_vip_nd(self, vlan, priority, faucet_vip, faucet_vip_host):
     faucet_vip_host_nd_mcast = valve_packet.ipv6_link_eth_mcast(
         valve_packet.ipv6_solicited_node_from_ucast(faucet_vip.ip))
     controller_and_flood = [
         valve_of.apply_actions([valve_of.output_controller()]),
         valve_of.goto_table(self.flood_table)]
     ofmsgs = []
     ofmsgs.append(self.eth_src_table.flowmod(
         self.eth_src_table.match(
             eth_type=self.ETH_TYPE,
             eth_dst=faucet_vip_host_nd_mcast,
             vlan=vlan,
             nw_proto=inet.IPPROTO_ICMPV6,
             icmpv6_type=icmpv6.ND_NEIGHBOR_SOLICIT),
         priority=priority,
         inst=controller_and_flood))
     ofmsgs.append(self.eth_src_table.flowcontroller(
         self.eth_src_table.match(
             eth_type=self.ETH_TYPE,
             eth_dst=vlan.faucet_mac,
             vlan=vlan,
             nw_proto=inet.IPPROTO_ICMPV6,
             icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT),
         priority=priority))
     if faucet_vip.ip in valve_packet.IPV6_LINK_LOCAL:
         ofmsgs.append(self.eth_src_table.flowmod(
             self.eth_src_table.match(
                 eth_type=self.ETH_TYPE,
                 eth_dst=valve_packet.IPV6_ALL_ROUTERS_MCAST,
                 vlan=vlan,
                 nw_proto=inet.IPPROTO_ICMPV6,
                 icmpv6_type=icmpv6.ND_ROUTER_SOLICIT),
             priority=priority,
             inst=controller_and_flood))
     return ofmsgs
Example #16
0
    def output(self, port, vlan, hairpin=False, external_forwarding_requested=None):
        """Get instructions list to output a packet through the regular
        pipeline.

        args:
            port: Port object of port to output packet to
            vlan: Vlan object of vlan to output packet on
            hairpin: if True, hairpinning is required
            apply_egress_acl: if True the packet will be sent to the egress acl
                table before being output
        returns:
            list of Instructions
        """
        instructions = []
        if self.egress_table:
            metadata, metadata_mask = faucet_md.get_egress_metadata(
                port.number, vlan.vid)
            if self.egress_acl_table:
                instructions.extend(valve_of.metadata_goto_table(
                    metadata, metadata_mask, self.egress_acl_table))
            else:
                instructions.extend(valve_of.metadata_goto_table(
                    metadata, metadata_mask, self.egress_table))
        else:
            instructions.append(valve_of.apply_actions(vlan.output_port(
                port, hairpin=hairpin, output_table=self.output_table,
                external_forwarding_requested=external_forwarding_requested)))
        return instructions
Example #17
0
 def add_faucet_vip(self, vlan, faucet_vip):
     ofmsgs = []
     max_prefixlen = faucet_vip.ip.max_prefixlen
     faucet_vip_host = self._host_from_faucet_vip(faucet_vip)
     priority = self.route_priority + max_prefixlen
     ofmsgs.append(self.valve_flowmod(
         self.eth_src_table,
         self.valve_in_match(
             self.eth_src_table,
             eth_type=ether.ETH_TYPE_ARP,
             nw_dst=faucet_vip_host,
             vlan=vlan),
         priority=priority,
         inst=[valve_of.apply_actions([valve_of.output_controller()])]))
     # Initialize IPv4 FIB
     ofmsgs.append(self.valve_flowmod(
         self.eth_src_table,
         self.valve_in_match(
             self.eth_src_table,
             eth_type=self._eth_type(),
             eth_dst=self.faucet_mac,
             vlan=vlan),
         priority=self.route_priority,
         inst=[valve_of.goto_table(self.fib_table)]))
     ofmsgs.append(self.valve_flowcontroller(
         self.fib_table,
         self.valve_in_match(
             self.fib_table,
             vlan=vlan,
             eth_type=self._eth_type(),
             nw_proto=inet.IPPROTO_ICMP,
             nw_src=faucet_vip,
             nw_dst=faucet_vip_host),
         priority=priority))
     return ofmsgs
Example #18
0
 def _add_faucet_fib_to_vip(self, vlan, priority, faucet_vip, faucet_vip_host):
     learn_connected_priority = self.route_priority + faucet_vip.network.prefixlen
     faucet_mac = vlan.faucet_mac
     insts = [valve_of.goto_table(self.fib_table)]
     if self._global_routing():
         vlan_mac = valve_packet.int_in_mac(faucet_mac, vlan.vid)
         insts = [valve_of.apply_actions([
             valve_of.set_eth_dst(vlan_mac),
             valve_of.set_vlan_vid(self.global_vlan.vid)])] + insts
     ofmsgs = []
     ofmsgs.append(self.eth_src_table.flowmod(
         self.eth_src_table.match(eth_type=self.ETH_TYPE, eth_dst=faucet_mac, vlan=vlan),
         priority=self.route_priority,
         inst=insts))
     routed_vlans = self._routed_vlans(vlan)
     if self._global_routing():
         vlan = self.global_vlan
     ofmsgs.append(self.fib_table.flowmod(
         self._route_match(vlan, faucet_vip_host),
         priority=priority,
         inst=[valve_of.goto_table(self.vip_table)]))
     if self.proactive_learn and not faucet_vip.ip.is_link_local:
         for routed_vlan in routed_vlans:
             ofmsgs.append(self.fib_table.flowmod(
                 self._route_match(routed_vlan, faucet_vip),
                 priority=learn_connected_priority,
                 inst=[valve_of.goto_table(self.vip_table)]))
         ofmsgs.append(self.vip_table.flowcontroller(
             self.vip_table.match(eth_type=self.ETH_TYPE),
             priority=priority-1,
             max_len=self.MAX_LEN))
     return ofmsgs
Example #19
0
def build_tunnel_ofmsgs(rule_conf, acl_table, priority,
                        port_num=None, vlan_vid=None, flowdel=False,
                        reverse=False):
    """Build a specific tunnel only ofmsgs"""
    ofmsgs = []
    acl_inst = []
    acl_match = []
    acl_match_dict = {}
    _, output_actions, output_ofmsgs, output_inst = build_output_actions(acl_table, rule_conf)
    ofmsgs.extend(output_ofmsgs)
    acl_inst.extend(output_inst)
    acl_inst.append(valve_of.apply_actions(output_actions))
    if port_num is not None:
        acl_match_dict['in_port'] = port_num
    if vlan_vid is not None:
        acl_match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    if reverse:
        acl_match_dict['vlan_pcp'] = valve_of.PCP_TUNNEL_REVERSE_DIRECTION_FLAG
    else:
        acl_match_dict['vlan_pcp'] = valve_of.PCP_TUNNEL_FLAG
    try:
        acl_match = valve_of.match_from_dict(acl_match_dict)
    except TypeError as type_error:
        raise InvalidConfigError('invalid match type in ACL') from type_error
    flowmod = acl_table.flowmod(acl_match, priority=priority, inst=tuple(acl_inst))
    if flowdel:
        ofmsgs.append(acl_table.flowdel(match=acl_match, priority=priority, strict=False))
    ofmsgs.append(flowmod)
    return ofmsgs
Example #20
0
 def _build_flood_rule(self, match, command, flood_acts, flood_priority):
     return [
         self.flood_table.flowmod(match=match,
                                  command=command,
                                  inst=[valve_of.apply_actions(flood_acts)],
                                  priority=flood_priority)
     ]
Example #21
0
    def create_mab_flow(self, port_num, nfv_sw_port_num, mac):
        """
        Create MAB ACL for sending IP Activity to Chewie NFV
            Returns flowmods to send all IP traffic to Chewie

        Args:
            port_num (int): Number of port in
            nfv_sw_port_num(int): Number of port out
            mac(str): MAC address of the valve/port combo

        """
        return self.port_acl_table.flowmod(
            match=self.port_acl_table.match(
                in_port=port_num,
                eth_type=valve_of.ether.ETH_TYPE_IP,
                nw_proto=valve_of.inet.IPPROTO_UDP,
                udp_src=68,
                udp_dst=67,
            ),
            priority=self.low_priority,
            inst=(valve_of.apply_actions([
                self.port_acl_table.set_field(eth_dst=mac),
                valve_of.output_port(nfv_sw_port_num)
            ]), ),
        )
Example #22
0
 def _build_group_flood_rules(self, vlan, modify, command):
     """Build flooding rules for a VLAN using groups."""
     flood_priority = self.flood_priority
     broadcast_group = self.groups.get_entry(
         vlan.vid, self._build_group_buckets(vlan, False))
     unicast_group = self.groups.get_entry(
         vlan.vid + valve_of.VLAN_GROUP_OFFSET,
         self._build_group_buckets(vlan, vlan.unicast_flood))
     ofmsgs = []
     if modify:
         ofmsgs.append(broadcast_group.modify())
         ofmsgs.append(unicast_group.modify())
     else:
         ofmsgs.extend(broadcast_group.add())
         ofmsgs.extend(unicast_group.add())
     for unicast_eth_dst, eth_dst, eth_dst_mask in self.FLOOD_DSTS:
         if unicast_eth_dst and not vlan.unicast_flood:
             continue
         group = broadcast_group
         if not eth_dst:
             group = unicast_group
         match = self.flood_table.match(vlan=vlan,
                                        eth_dst=eth_dst,
                                        eth_dst_mask=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))
         flood_priority += 1
     return ofmsgs
Example #23
0
 def _build_group_flood_rules(self, vlan, modify, command):
     """Build flooding rules for a VLAN using groups."""
     flood_priority = self.flood_priority
     broadcast_group = self.groups.get_entry(
         vlan.vid,
         self._build_group_buckets(vlan, False))
     unicast_group = self.groups.get_entry(
         vlan.vid + valve_of.VLAN_GROUP_OFFSET,
         self._build_group_buckets(vlan, vlan.unicast_flood))
     ofmsgs = []
     if modify:
         ofmsgs.append(broadcast_group.modify())
         ofmsgs.append(unicast_group.modify())
     else:
         ofmsgs.extend(broadcast_group.add())
         ofmsgs.extend(unicast_group.add())
     for unicast_eth_dst, eth_dst, eth_dst_mask in self.FLOOD_DSTS:
         if unicast_eth_dst and not vlan.unicast_flood:
             continue
         group = broadcast_group
         if not eth_dst:
             group = unicast_group
         match = self.flood_table.match(
             vlan=vlan, eth_dst=eth_dst, eth_dst_mask=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))
         flood_priority += 1
     return ofmsgs
Example #24
0
    def output(self, port, vlan, hairpin=False, loop_protect_field=None):
        """Get instructions list to output a packet through the regular
        pipeline.

        args:
            port: Port object of port to output packet to
            vlan: Vlan object of vlan to output packet on
            hairpin: if True, hairpinning is required
        returns:
            list of Instructions
        """
        instructions = []
        if self.egress_table:
            metadata, metadata_mask = faucet_md.get_egress_metadata(
                port.number, vlan.vid)
            instructions.extend(
                valve_of.metadata_goto_table(metadata, metadata_mask,
                                             self.egress_table))
        else:
            instructions.append(
                valve_of.apply_actions(
                    vlan.output_port(port,
                                     hairpin=hairpin,
                                     output_table=self.output_table,
                                     loop_protect_field=loop_protect_field)))
        return instructions
Example #25
0
    def learn_host_on_vlan_port_flows(self, port, vlan, eth_src,
                                      delete_existing, refresh_rules,
                                      src_rule_idle_timeout,
                                      src_rule_hard_timeout,
                                      dst_rule_idle_timeout):
        """Return flows that implement learning a host on a port."""
        ofmsgs = []

        # Delete any existing entries for MAC.
        if delete_existing:
            ofmsgs.extend(self.delete_host_from_vlan(eth_src, vlan))

        # Associate this MAC with source port.
        src_match = self.eth_src_table.match(
            in_port=port.number, vlan=vlan, eth_src=eth_src)
        src_priority = self.host_priority - 1
        inst = self.eth_src_table.goto(self.output_table)

        if port.override_output_port:
            inst = valve_of.apply_actions([
                valve_of.output_port(port.override_output_port.number)])

        loop_protect_field = None
        if port.tagged_vlans and port.loop_protect_external and self.stack:
            loop_protect_field = 0

        ofmsgs.append(self.eth_src_table.flowmod(
            match=src_match,
            priority=src_priority,
            inst=[inst],
            hard_timeout=src_rule_hard_timeout,
            idle_timeout=src_rule_idle_timeout))

        hairpinning = port.hairpin or port.hairpin_unicast

        # If we are refreshing only and not in hairpin mode, leave existing eth_dst alone.
        if refresh_rules and not hairpinning:
            return ofmsgs

        # Output packets for this MAC to specified port.
        ofmsgs.append(self.eth_dst_table.flowmod(
            self.eth_dst_table.match(vlan=vlan, eth_dst=eth_src),
            priority=self.host_priority,
            inst=self.pipeline.output(port, vlan, loop_protect_field=loop_protect_field),
            idle_timeout=dst_rule_idle_timeout))

        # If port is in hairpin mode, install a special rule
        # that outputs packets destined to this MAC back out the same
        # port they came in (e.g. multiple hosts on same WiFi AP,
        # and FAUCET is switching between them on the same port).
        if hairpinning:
            ofmsgs.append(self.eth_dst_hairpin_table.flowmod(
                self.eth_dst_hairpin_table.match(in_port=port.number, vlan=vlan, eth_dst=eth_src),
                priority=self.host_priority,
                inst=self.pipeline.output(port, vlan, hairpin=True),
                idle_timeout=dst_rule_idle_timeout))

        return ofmsgs
Example #26
0
    def learn_host_on_vlan_port_flows(self, port, vlan, eth_src,
                                      delete_existing, refresh_rules,
                                      src_rule_idle_timeout,
                                      src_rule_hard_timeout,
                                      dst_rule_idle_timeout):
        """Return flows that implement learning a host on a port."""
        ofmsgs = []

        # Delete any existing entries for MAC.
        if delete_existing:
            ofmsgs.extend(self.delete_host_from_vlan(eth_src, vlan))

        # Associate this MAC with source port.
        src_match = self.eth_src_table.match(in_port=port.number,
                                             vlan=vlan,
                                             eth_src=eth_src)
        src_priority = self.host_priority - 1
        inst = self.eth_src_table.goto(self.output_table)

        if port.override_output_port:
            inst = valve_of.apply_actions(
                [valve_of.output_port(port.override_output_port.number)])
        ofmsgs.append(
            self.eth_src_table.flowmod(match=src_match,
                                       priority=src_priority,
                                       inst=[inst],
                                       hard_timeout=src_rule_hard_timeout,
                                       idle_timeout=src_rule_idle_timeout))

        hairpinning = port.hairpin or port.hairpin_unicast

        # If we are refreshing only and not in hairpin mode, leave existing eth_dst alone.
        if refresh_rules and not hairpinning:
            return ofmsgs

        # Output packets for this MAC to specified port.
        ofmsgs.append(
            self.eth_dst_table.flowmod(self.eth_dst_table.match(
                vlan=vlan, eth_dst=eth_src),
                                       priority=self.host_priority,
                                       inst=self.pipeline.output(port, vlan),
                                       idle_timeout=dst_rule_idle_timeout))

        # If port is in hairpin mode, install a special rule
        # that outputs packets destined to this MAC back out the same
        # port they came in (e.g. multiple hosts on same WiFi AP,
        # and FAUCET is switching between them on the same port).
        if hairpinning:
            ofmsgs.append(
                self.eth_dst_hairpin_table.flowmod(
                    self.eth_dst_hairpin_table.match(in_port=port.number,
                                                     vlan=vlan,
                                                     eth_dst=eth_src),
                    priority=self.host_priority,
                    inst=self.pipeline.output(port, vlan, hairpin=True),
                    idle_timeout=dst_rule_idle_timeout))

        return ofmsgs
Example #27
0
 def _port_add_vlan_untagged(self, port, vlan, forwarding_table, mirror_act):
     push_vlan_act = mirror_act + valve_of.push_vlan_act(vlan.vid)
     push_vlan_inst = [
         valve_of.apply_actions(push_vlan_act),
         valve_of.goto_table(forwarding_table)
     ]
     null_vlan = namedtuple('null_vlan', 'vid')
     null_vlan.vid = valve_of.ofp.OFPVID_NONE
     return self._port_add_vlan_rules(port, null_vlan, push_vlan_inst)
Example #28
0
 def flowcontroller(self, match=None, priority=None, inst=None, max_len=96):
     """Add flow outputting to controller."""
     if inst is None:
         inst = ()
     return self.flowmod(match=match,
                         priority=priority,
                         inst=(valve_of.apply_actions(
                             (valve_of.output_controller(max_len), )), ) +
                         inst)
Example #29
0
 def flowcontroller(self, match=None, priority=None, inst=None, max_len=96):
     """Add flow outputting to controller."""
     if inst is None:
         inst = []
     return self.flowmod(
         match=match,
         priority=priority,
         inst=[valve_of.apply_actions(
             [valve_of.output_controller(max_len)])] + inst)
Example #30
0
 def _add_faucet_vip_nd(self, vlan, priority, faucet_vip, faucet_vip_host):
     faucet_vip_host_nd_mcast = valve_packet.ipv6_link_eth_mcast(
         valve_packet.ipv6_solicited_node_from_ucast(faucet_vip.ip))
     controller_and_flood = [
         valve_of.apply_actions([valve_of.output_controller()]),
         self.vip_table.goto(self.output_table)
     ]
     ofmsgs = []
     ofmsgs.append(
         self.vip_table.flowcontroller(self.vip_table.match(
             eth_type=self.ETH_TYPE,
             nw_proto=valve_of.inet.IPPROTO_ICMPV6,
             icmpv6_type=icmpv6.ICMPV6_ECHO_REQUEST),
                                       priority=priority,
                                       max_len=self.MAX_LEN))
     # IPv6 ND for FAUCET VIP
     ofmsgs.append(
         self.eth_src_table.flowmod(
             self.eth_src_table.match(eth_type=self.ETH_TYPE,
                                      eth_dst=faucet_vip_host_nd_mcast,
                                      vlan=vlan),
             priority=priority,
             inst=[self.eth_src_table.goto(self.vip_table)]))
     ofmsgs.append(
         self.vip_table.flowmod(self.vip_table.match(
             eth_type=self.ETH_TYPE,
             nw_proto=valve_of.inet.IPPROTO_ICMPV6,
             icmpv6_type=icmpv6.ND_NEIGHBOR_SOLICIT),
                                priority=priority,
                                inst=controller_and_flood))
     # IPv6 ND for connected hosts.
     ofmsgs.append(
         self.vip_table.flowcontroller(self.vip_table.match(
             eth_type=self.ETH_TYPE,
             eth_dst=vlan.faucet_mac,
             nw_proto=valve_of.inet.IPPROTO_ICMPV6,
             icmpv6_type=icmpv6.ND_NEIGHBOR_ADVERT),
                                       priority=priority,
                                       max_len=self.MAX_LEN))
     if faucet_vip.ip.is_link_local:
         ofmsgs.append(
             self.eth_src_table.flowmod(
                 self.eth_src_table.match(
                     eth_type=self.ETH_TYPE,
                     eth_dst=valve_packet.IPV6_ALL_ROUTERS_MCAST,
                     vlan=vlan),
                 priority=priority,
                 inst=[self.eth_src_table.goto(self.vip_table)]))
         ofmsgs.append(
             self.vip_table.flowmod(self.vip_table.match(
                 eth_type=self.ETH_TYPE,
                 nw_proto=valve_of.inet.IPPROTO_ICMPV6,
                 icmpv6_type=icmpv6.ND_ROUTER_SOLICIT),
                                    priority=priority,
                                    inst=controller_and_flood))
     return ofmsgs
Example #31
0
 def select_packets(self, target_table, match_dict, actions=None,
                    priority_offset=0):
     """retrieve rules to redirect packets matching match_dict to table"""
     inst = [target_table.goto_this()]
     if actions is not None:
         inst.append(valve_of.apply_actions(actions))
     return [self.classification_table.flowmod(
         self.classification_table.match(**match_dict),
         priority=self.select_priority + priority_offset,
         inst=inst)]
Example #32
0
 def select_packets(self, target_table, match_dict, actions=None,
                    priority_offset=0):
     """retrieve rules to redirect packets matching match_dict to table"""
     inst = [target_table.goto_this()]
     if actions is not None:
         inst.append(valve_of.apply_actions(actions))
     return [self.classification_table.flowmod(
         self.classification_table.match(**match_dict),
         priority=self.select_priority + priority_offset,
         inst=inst)]
Example #33
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 #34
0
    def _build_group_flood_rules(self, vlan, modify, command):
        """Build flooding rules for a VLAN using groups."""
        ofmsgs = []
        groups_by_unicast_eth = {}

        _, vlan_flood_acts = self._build_flood_rule_for_vlan(
            vlan, 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
        groups_by_unicast_eth[True] = group

        # 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, True, command)
        unicast_eth_vlan_flood_acts, unicast_output_ports, _ = self._output_non_output_actions(
            unicast_eth_vlan_flood_acts)
        vlan_flood_acts, vlan_output_ports, _ = self._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_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_dst=eth_dst,
                                           eth_dst_mask=eth_dst_mask)
            flood_priority = self._mask_flood_priority(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
Example #35
0
 def _add_egress_table_rule(self, port, vlan, pop_vlan=True):
     metadata, metadata_mask = faucet_md.get_egress_metadata(
         port.number, vlan.vid)
     actions = copy.copy(port.mirror_actions())
     if pop_vlan:
         actions.append(valve_of.pop_vlan())
     actions.append(valve_of.output_port(port.number))
     inst = (valve_of.apply_actions(tuple(actions)), )
     return self.egress_table.flowmod(self.egress_table.match(
         vlan=vlan, metadata=metadata, metadata_mask=metadata_mask),
                                      priority=self.dp.high_priority,
                                      inst=inst)
Example #36
0
 def accept_to_l2_forwarding(self, actions=None):
     """Get instructions to forward packet through the pipeline to l2
     forwarding.
     args:
         actions: (optional) list of actions to apply to packet.
     returns:
         list of instructions
     """
     inst = [self.output_table.goto_this()]
     if actions is not None:
         inst.append(valve_of.apply_actions(actions))
     return inst
Example #37
0
 def add_port(self, port):
     """initialise override_output_port if necessary"""
     ofmsgs = []
     if port.override_output_port:
         ofmsgs.append(self.eth_src_table.flowmod(
             match=self.eth_src_table.match(
                 in_port=port.number),
             priority=self.low_priority + 1,
             inst=[valve_of.apply_actions([
                 valve_of.output_controller(),
                 valve_of.output_port(port.override_output_port.number)])]))
     return ofmsgs
Example #38
0
 def add_port(self, port):
     """initialise override_output_port if necessary"""
     ofmsgs = []
     if port.override_output_port:
         ofmsgs.append(self.eth_src_table.flowmod(
             match=self.eth_src_table.match(
                 in_port=port.number),
             priority=self.low_priority + 1,
             inst=[valve_of.apply_actions([
                 valve_of.output_controller(),
                 valve_of.output_port(port.override_output_port.number)])]))
     return ofmsgs
Example #39
0
 def _build_flood_rule_for_vlan(self, vlan, eth_dst, eth_dst_mask, # pylint: disable=too-many-arguments
                                exclude_unicast, command, flood_priority,
                                preflood_acts):
     ofmsgs = []
     match = self.flood_table.match(
         vlan=vlan, eth_dst=eth_dst, eth_dst_mask=eth_dst_mask)
     flood_acts = self._build_flood_rule_actions(
         vlan, exclude_unicast, None)
     ofmsgs.append(self.flood_table.flowmod(
         match=match,
         command=command,
         inst=[valve_of.apply_actions(preflood_acts + flood_acts)],
         priority=flood_priority))
     return ofmsgs
Example #40
0
 def _add_egress_table_rule(self, port, vlan, pop_vlan=True):
     metadata, metadata_mask = faucet_md.get_egress_metadata(
         port.number, vlan.vid)
     actions = copy.copy(port.mirror_actions())
     if pop_vlan:
         actions.append(valve_of.pop_vlan())
     actions.append(valve_of.output_port(port.number))
     inst = [valve_of.apply_actions(actions)]
     return self.egress_table.flowmod(
         self.egress_table.match(
             vlan=vlan,
             metadata=metadata,
             metadata_mask=metadata_mask
             ),
         priority=self.dp.high_priority,
         inst=inst
         )
Example #41
0
    def _build_group_flood_rules(self, vlan, modify, command):
        """Build flooding rules for a VLAN using groups."""
        ofmsgs = []
        groups_by_unicast_eth = {}

        _, vlan_flood_acts = self._build_flood_rule_for_vlan(
            vlan, 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
        groups_by_unicast_eth[True] = group

        # 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, True, command)
        unicast_eth_vlan_flood_acts, unicast_output_ports, _ = self._output_non_output_actions(
            unicast_eth_vlan_flood_acts)
        vlan_flood_acts, vlan_output_ports, _ = self._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_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_dst=eth_dst, eth_dst_mask=eth_dst_mask)
            flood_priority = self._mask_flood_priority(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
Example #42
0
 def _add_resolved_route(self, vlan, ip_gw, ip_dst, eth_dst, is_updated):
     ofmsgs = []
     if is_updated:
         self.logger.info(
             'Updating next hop for route %s via %s (%s) on VLAN %u' % (
                 ip_dst, ip_gw, eth_dst, vlan.vid))
         ofmsgs.extend(self._del_route_flows(vlan, ip_dst))
     else:
         self.logger.info(
             'Adding new route %s via %s (%s) on VLAN %u' % (
                 ip_dst, ip_gw, eth_dst, vlan.vid))
     inst = [valve_of.apply_actions(self._nexthop_actions(eth_dst, vlan)),
             self.fib_table.goto(self.output_table)]
     routed_vlans = self._routed_vlans(vlan)
     for routed_vlan in routed_vlans:
         in_match = self._route_match(routed_vlan, ip_dst)
         ofmsgs.append(self.fib_table.flowmod(
             in_match, priority=self._route_priority(ip_dst), inst=inst))
     return ofmsgs
Example #43
0
    def output(self, port, vlan, hairpin=False):
        """Get instructions list to output a packet through the regular
        pipeline.

        args:
            port: Port object of port to output packet to
            vlan: Vlan object of vlan to output packet on
            hairpin: if True, hairpinning is required
        returns:
            list of Instructions
        """
        instructions = []
        if self.egress_table:
            metadata, metadata_mask = faucet_md.get_egress_metadata(
                port.number, vlan.vid)
            instructions.extend(valve_of.metadata_goto_table(
                metadata, metadata_mask, self.egress_table))
        else:
            instructions.append(valve_of.apply_actions(vlan.output_port(port, hairpin=hairpin)))
        return instructions
Example #44
0
 def _add_faucet_fib_to_vip(self, vlan, priority, faucet_vip, faucet_vip_host):
     ofmsgs = []
     learn_connected_priority = self.route_priority + faucet_vip.network.prefixlen
     faucet_mac = vlan.faucet_mac
     insts = [self.classification_table.goto(self.fib_table)]
     if self.global_routing:
         vlan_mac = valve_packet.int_in_mac(faucet_mac, vlan.vid)
         insts = [valve_of.apply_actions([
             self.fib_table.set_field(eth_dst=vlan_mac),
             self.fib_table.set_vlan_vid(self.global_vlan.vid)])] + insts
     ofmsgs.append(self.classification_table.flowmod(
         self.classification_table.match(
             eth_type=self.ETH_TYPE, eth_dst=faucet_mac, vlan=vlan),
         priority=self.route_priority,
         inst=insts))
     if self.global_routing:
         vlan = self.global_vlan
     ofmsgs.append(self.fib_table.flowmod(
         self._route_match(vlan, faucet_vip_host),
         priority=priority,
         inst=[self.fib_table.goto(self.vip_table)]))
     if self.proactive_learn and not faucet_vip.ip.is_link_local:
         routed_vlans = self._routed_vlans(vlan)
         for routed_vlan in routed_vlans:
             ofmsgs.append(self.fib_table.flowmod(
                 self._route_match(routed_vlan, faucet_vip),
                 priority=learn_connected_priority,
                 inst=[self.fib_table.goto(self.vip_table)]))
         # Unicast ICMP to us.
         priority -= 1
         ofmsgs.append(self.vip_table.flowcontroller(
             self.vip_table.match(
                 eth_type=self.ETH_TYPE,
                 eth_dst=faucet_mac,
                 nw_proto=self.ICMP_TYPE),
             priority=priority,
             max_len=self.ICMP_SIZE))
         # Learn + flood other ICMP not unicast to us.
         priority -= 1
         ofmsgs.append(self.vip_table.flowmod(
             self.vip_table.match(
                 eth_type=self.ETH_TYPE,
                 nw_proto=self.ICMP_TYPE),
             priority=priority,
             inst=self._controller_and_flood()))
         # Learn from other IP traffic unicast to us.
         priority -= 1
         ofmsgs.append(self.vip_table.flowcontroller(
             self.vip_table.match(
                 eth_type=self.ETH_TYPE,
                 eth_dst=faucet_mac),
             priority=priority,
             max_len=self.ICMP_SIZE))
         # Learn + flood IP traffic not unicast to us.
         priority -= 1
         ofmsgs.append(self.vip_table.flowmod(
             self.vip_table.match(
                 eth_type=self.ETH_TYPE),
             priority=priority,
             inst=self._controller_and_flood()))
     return ofmsgs
Example #45
0
 def _controller_and_flood(self):
     return [
         valve_of.apply_actions([valve_of.output_controller(max_len=self.ICMP_SIZE)]),
         self.vip_table.goto(self.output_table)]
Example #46
0
    def learn_host_on_vlan_port_flows(self, port, vlan, eth_src,
                                      delete_existing, refresh_rules,
                                      src_rule_idle_timeout,
                                      src_rule_hard_timeout,
                                      dst_rule_idle_timeout):
        """Return flows that implement learning a host on a port."""
        ofmsgs = []

        if port.permanent_learn:
            # Antispoofing rule for this MAC.
            if self.classification_table != self.eth_src_table:
                ofmsgs.append(self.classification_table.flowmod(
                    self.classification_table.match(
                        in_port=port.number, vlan=vlan, eth_src=eth_src),
                    priority=self.host_priority,
                    inst=[self.classification_table.goto(self.eth_src_table)]))
            ofmsgs.append(self.classification_table.flowdrop(
                self.classification_table.match(vlan=vlan, eth_src=eth_src),
                priority=(self.host_priority - 2)))
        else:
            # Delete any existing entries for MAC.
            if delete_existing:
                ofmsgs.extend(self.delete_host_from_vlan(eth_src, vlan))

        # Associate this MAC with source port.
        src_match = self.eth_src_table.match(
            in_port=port.number, vlan=vlan, eth_src=eth_src)
        src_priority = self.host_priority - 1
        inst = self.eth_src_table.goto(self.output_table)

        if port.override_output_port:
            inst = valve_of.apply_actions([
                valve_of.output_port(port.override_output_port.number)])
        ofmsgs.append(self.eth_src_table.flowmod(
            match=src_match,
            priority=src_priority,
            inst=[inst],
            hard_timeout=src_rule_hard_timeout,
            idle_timeout=src_rule_idle_timeout))

        hairpinning = port.hairpin or port.hairpin_unicast

        # If we are refreshing only and not in hairpin mode, leave existing eth_dst alone.
        if refresh_rules and not hairpinning:
            return ofmsgs

        # Output packets for this MAC to specified port.
        if self.egress_table is not None:
            metadata, metadata_mask = get_egress_metadata(port.number, vlan.vid)
            ofmsgs.append(self.eth_dst_table.flowmod(
                self.eth_dst_table.match(vlan=vlan, eth_dst=eth_src),
                priority=self.host_priority,
                inst=valve_of.metadata_goto_table(
                    metadata, metadata_mask, self.egress_table),
                idle_timeout=dst_rule_idle_timeout))
        else:
            ofmsgs.append(self.eth_dst_table.flowmod(
                self.eth_dst_table.match(vlan=vlan, eth_dst=eth_src),
                priority=self.host_priority,
                inst=[valve_of.apply_actions(vlan.output_port(port))],
                idle_timeout=dst_rule_idle_timeout))

        # If port is in hairpin mode, install a special rule
        # that outputs packets destined to this MAC back out the same
        # port they came in (e.g. multiple hosts on same WiFi AP,
        # and FAUCET is switching between them on the same port).
        if hairpinning:
            ofmsgs.append(self.eth_dst_hairpin_table.flowmod(
                self.eth_dst_hairpin_table.match(in_port=port.number, vlan=vlan, eth_dst=eth_src),
                priority=self.host_priority,
                inst=[valve_of.apply_actions(vlan.output_port(port, hairpin=True))],
                idle_timeout=dst_rule_idle_timeout))

        return ofmsgs
Example #47
0
def build_acl_entry(acl_table, rule_conf, meters,
                    acl_allow_inst, acl_force_port_vlan_inst,
                    port_num=None, vlan_vid=None):
    """Build flow/groupmods for one ACL rule entry."""
    acl_inst = []
    acl_act = []
    acl_match_dict = {}
    acl_ofmsgs = []
    acl_cookie = None
    allow_inst = acl_allow_inst

    for attrib, attrib_value in rule_conf.items():
        if attrib == 'in_port':
            continue
        if attrib == 'cookie':
            acl_cookie = attrib_value
            continue
        if attrib == 'description':
            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 'force_port_vlan' in attrib_value:
                if attrib_value['force_port_vlan'] == 1:
                    allow_inst = acl_force_port_vlan_inst
            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_act.append(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(
                    acl_table, attrib_value['output'])
                acl_act.extend(output_actions)
                acl_ofmsgs.extend(output_ofmsgs)

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

            if allow:
                acl_inst.extend(allow_inst)
        else:
            acl_match_dict[attrib] = attrib_value
    if port_num is not None:
        acl_match_dict['in_port'] = port_num
    if vlan_vid is not None:
        acl_match_dict['vlan_vid'] = valve_of.vid_present(vlan_vid)
    try:
        acl_match = valve_of.match_from_dict(acl_match_dict)
    except TypeError:
        raise InvalidConfigError('invalid type in ACL')
    if acl_act:
        acl_inst.append(valve_of.apply_actions(acl_act))
    return (acl_match, acl_inst, acl_cookie, acl_ofmsgs)
Example #48
0
 def _build_flood_rule(self, match, command, flood_acts, flood_priority):
     return self.flood_table.flowmod(
         match=match,
         command=command,
         inst=[valve_of.apply_actions(flood_acts)],
         priority=flood_priority)
Example #49
0
 def _accept_to_table(self, table, actions):
     inst = [table.goto_this()]
     if actions is not None:
         inst.append(valve_of.apply_actions(actions))
     return inst