Esempio n. 1
0
 def _flood_stack_links(self, pkt_builder, vlan, multi_out=True, *args):
     """Return flood packet-out actions to stack ports for gw resolving"""
     ofmsgs = []
     if self.stack_manager:
         ports = []
         if self.stack_manager.stack.is_root():
             ports = list(self.stack_manager.away_ports -
                          self.stack_manager.inactive_away_ports -
                          self.stack_manager.pruned_away_ports)
         else:
             if self.stack_manager.chosen_towards_port is not None:
                 ports = [self.stack_manager.chosen_towards_port]
         if ports:
             running_port_nos = [
                 port.number for port in ports if port.running()
             ]
             pkt = pkt_builder(vlan.vid, *args)
             if running_port_nos:
                 random.shuffle(running_port_nos)
                 if multi_out:
                     ofmsgs.append(
                         valve_of.packetouts(running_port_nos,
                                             bytes(pkt.data)))
                 else:
                     ofmsgs.extend([
                         valve_of.packetout(port_no, bytes(pkt.data))
                         for port_no in running_port_nos
                     ])
     return ofmsgs
Esempio n. 2
0
 def _control_plane_arp_handler(self, pkt_meta):
     ofmsgs = []
     pkt_meta.reparse_ip(ether.ETH_TYPE_ARP)
     arp_pkt = pkt_meta.pkt.get_protocol(arp.arp)
     if arp_pkt is None:
         return ofmsgs
     src_ip = ipaddress.IPv4Address(btos(arp_pkt.src_ip))
     dst_ip = ipaddress.IPv4Address(btos(arp_pkt.dst_ip))
     vlan = pkt_meta.vlan
     if vlan.from_connected_to_vip(src_ip, dst_ip):
         opcode = arp_pkt.opcode
         port = pkt_meta.port
         eth_src = pkt_meta.eth_src
         vid = self._vlan_vid(vlan, port)
         if opcode == arp.ARP_REQUEST:
             ofmsgs.extend(
                 self._add_host_fib_route(vlan, src_ip))
             ofmsgs.extend(self._update_nexthop(
                 vlan, port, eth_src, src_ip))
             arp_reply = valve_packet.arp_reply(
                 vid, vlan.faucet_mac, eth_src, dst_ip, src_ip)
             ofmsgs.append(
                 valve_of.packetout(port.number, arp_reply.data))
             self.logger.info(
                 'Responded to ARP request for %s from %s (%s) on VLAN %u' % (
                     dst_ip, src_ip, eth_src, vlan.vid))
         elif (opcode == arp.ARP_REPLY and
               pkt_meta.eth_dst == vlan.faucet_mac):
             ofmsgs.extend(
                 self._update_nexthop(vlan, port, eth_src, src_ip))
             self.logger.info(
                 'ARP response %s (%s) on VLAN %u' % (
                     src_ip, eth_src, vlan.vid))
     return ofmsgs
Esempio n. 3
0
File: vlan.py Progetto: mubix/faucet
 def pkt_out_port(self, packet_builder, port, *args):
     """Return packet-out actions with VLAN tag if port is tagged"""
     vid = None
     if self.port_is_tagged(port):
         vid = self.vid
     pkt = packet_builder(vid, *args)
     return valve_of.packetout(port.number, pkt.data)
Esempio n. 4
0
    def _control_plane_icmp_handler(self, pkt_meta, ipv4_pkt):
        ofmsgs = []
        if not pkt_meta.packet_complete():
            return ofmsgs

        src_ip = ipaddress.IPv4Address(btos(ipv4_pkt.src))
        dst_ip = ipaddress.IPv4Address(btos(ipv4_pkt.dst))
        vlan = pkt_meta.vlan
        if vlan.from_connected_to_vip(src_ip, dst_ip):
            if pkt_meta.eth_dst != vlan.faucet_mac:
                return ofmsgs
            if ipv4_pkt.proto != valve_of.inet.IPPROTO_ICMP:
                return ofmsgs
            pkt_meta.reparse_all()
            icmp_pkt = pkt_meta.pkt.get_protocol(icmp.icmp)
            if icmp_pkt is None:
                return ofmsgs
            if icmp_pkt.type == icmp.ICMP_ECHO_REQUEST:
                port = pkt_meta.port
                vid = self._vlan_vid(vlan, port)
                echo_reply = valve_packet.echo_reply(
                    vid, vlan.faucet_mac, pkt_meta.eth_src,
                    dst_ip, src_ip, icmp_pkt.data)
                ofmsgs.append(
                    valve_of.packetout(port.number, echo_reply.data))
        return ofmsgs
Esempio n. 5
0
 def _control_plane_arp_handler(self, pkt_meta, arp_pkt):
     src_ip = ipaddress.IPv4Address(btos(arp_pkt.src_ip))
     dst_ip = ipaddress.IPv4Address(btos(arp_pkt.dst_ip))
     vlan = pkt_meta.vlan
     opcode = arp_pkt.opcode
     ofmsgs = []
     if vlan.from_connected_to_vip(src_ip, dst_ip):
         in_port = pkt_meta.port.number
         eth_src = pkt_meta.eth_src
         if opcode == arp.ARP_REQUEST:
             ofmsgs.extend(
                 self._add_host_fib_route(vlan, src_ip))
             vid = self._vlan_vid(vlan, in_port)
             arp_reply = valve_packet.arp_reply(
                 self.faucet_mac, eth_src, vid, dst_ip, src_ip)
             ofmsgs.append(
                 valve_of.packetout(in_port, arp_reply.data))
             self.logger.info(
                 'Responded to ARP request for %s from %s (%s)',
                 dst_ip, src_ip, eth_src)
         elif (opcode == arp.ARP_REPLY and
               pkt_meta.eth_dst == self.faucet_mac):
             ofmsgs.extend(
                 self._update_nexthop(vlan, in_port, eth_src, src_ip))
             self.logger.info(
                 'ARP response %s (%s)', src_ip, eth_src)
     return ofmsgs
Esempio n. 6
0
 def flood_pkt(self, packet_builder, *args):
     ofmsgs = []
     for vid, ports in (
             (self.vid, self.tagged_flood_ports(False)),
             (None, self.untagged_flood_ports(False))):
         if ports:
             pkt = packet_builder(vid, *args)
             flood_ofmsgs = [valve_of.packetout(port.number, pkt.data) for port in ports if port.running()]
             ofmsgs.extend(flood_ofmsgs)
     return ofmsgs
Esempio n. 7
0
 def _neighbor_resolver(self, ip_gw, faucet_vip, vlan, ports):
     ofmsgs = []
     if ports:
         port_num = ports[0].number
         vid = self._vlan_vid(vlan, port_num)
         resolver_pkt = self._neighbor_resolver_pkt(
             vid, faucet_vip, ip_gw)
         for port in ports:
             ofmsgs.append(valve_of.packetout(
                 port.number, resolver_pkt.data))
     return ofmsgs
    def lacp_req_reply(self, lacp_pkt, port):
        """
        Constructs a LACP req-reply packet.

        Args:
            lacp_pkt (PacketMeta): LACP packet received
            port: LACP port
            other_valves (list): List of other valves

        Returns:
            list packetout OpenFlow msgs.
        """
        if port.lacp_passthrough:
            for peer_num in port.lacp_passthrough:
                lacp_peer = self.ports.get(peer_num, None)
                if not lacp_peer.dyn_lacp_up:
                    self.logger.warning(
                        'Suppressing LACP LAG %s on %s, peer %s link is down' %
                        (port.lacp, port, lacp_peer))
                    return []
        actor_state_activity = 0
        if port.lacp_active:
            actor_state_activity = 1
        actor_state_sync, actor_state_col, actor_state_dist = port.get_lacp_flags(
        )
        if lacp_pkt:
            pkt = valve_packet.lacp_reqreply(
                self.faucet_dp_mac, self.faucet_dp_mac, port.lacp,
                port.lacp_port_id, port.lacp_port_priority, actor_state_sync,
                actor_state_activity, actor_state_col, actor_state_dist,
                lacp_pkt.actor_system, lacp_pkt.actor_key, lacp_pkt.actor_port,
                lacp_pkt.actor_system_priority, lacp_pkt.actor_port_priority,
                lacp_pkt.actor_state_defaulted, lacp_pkt.actor_state_expired,
                lacp_pkt.actor_state_timeout, lacp_pkt.actor_state_collecting,
                lacp_pkt.actor_state_distributing,
                lacp_pkt.actor_state_aggregation,
                lacp_pkt.actor_state_synchronization,
                lacp_pkt.actor_state_activity)
        else:
            pkt = valve_packet.lacp_reqreply(
                self.faucet_dp_mac,
                self.faucet_dp_mac,
                port.lacp,
                port.lacp_port_id,
                port.lacp_port_priority,
                actor_state_synchronization=actor_state_sync,
                actor_state_activity=actor_state_activity,
                actor_state_collecting=actor_state_col,
                actor_state_distributing=actor_state_dist)
        self.logger.debug('Sending LACP %s on %s activity %s' %
                          (pkt, port, actor_state_activity))
        return [valve_of.packetout(port.number, pkt.data)]
Esempio n. 9
0
 def _control_plane_icmpv6_handler(self, pkt_meta, ipv6_pkt, icmpv6_pkt):
     vlan = pkt_meta.vlan
     src_ip = ipaddress.IPv6Address(btos(ipv6_pkt.src))
     dst_ip = ipaddress.IPv6Address(btos(ipv6_pkt.dst))
     icmpv6_type = icmpv6_pkt.type_
     ofmsgs = []
     if vlan.ip_in_vip_subnet(src_ip):
         in_port = pkt_meta.port.number
         vid = self._vlan_vid(vlan, in_port)
         eth_src = pkt_meta.eth_src
         if icmpv6_type == icmpv6.ND_NEIGHBOR_SOLICIT:
             solicited_ip = btos(icmpv6_pkt.data.dst)
             if vlan.is_faucet_vip(ipaddress.ip_address(solicited_ip)):
                 ofmsgs.extend(
                     self._add_host_fib_route(vlan, src_ip))
                 nd_reply = valve_packet.nd_reply(
                     self.faucet_mac, eth_src, vid,
                     solicited_ip, src_ip, ipv6_pkt.hop_limit)
                 ofmsgs.append(
                     valve_of.packetout(in_port, nd_reply.data))
                 self.logger.info(
                     'Responded to ND solicit for %s to %s (%s)',
                     solicited_ip, src_ip, eth_src)
         elif icmpv6_type == icmpv6.ND_NEIGHBOR_ADVERT:
             ofmsgs.extend(self._update_nexthop(
                 vlan, in_port, eth_src, src_ip))
             self.logger.info(
                 'ND advert %s (%s)', src_ip, eth_src)
         elif vlan.from_connected_to_vip(src_ip, dst_ip):
             if (icmpv6_type == icmpv6.ICMPV6_ECHO_REQUEST and
                     pkt_meta.eth_dst == self.faucet_mac):
                 icmpv6_echo_reply = valve_packet.icmpv6_echo_reply(
                     self.faucet_mac, eth_src, vid,
                     dst_ip, src_ip, ipv6_pkt.hop_limit,
                     icmpv6_pkt.data.id, icmpv6_pkt.data.seq,
                     icmpv6_pkt.data.data)
                 ofmsgs.append(
                     valve_of.packetout(in_port, icmpv6_echo_reply.data))
     return ofmsgs
Esempio n. 10
0
 def _control_plane_icmp_handler(self, pkt_meta, ipv4_pkt, icmp_pkt):
     src_ip = ipaddress.IPv4Address(btos(ipv4_pkt.src))
     dst_ip = ipaddress.IPv4Address(btos(ipv4_pkt.dst))
     vlan = pkt_meta.vlan
     icmpv4_type = icmp_pkt.type
     ofmsgs = []
     if vlan.from_connected_to_vip(src_ip, dst_ip):
         if (icmpv4_type == icmp.ICMP_ECHO_REQUEST and
                 pkt_meta.eth_dst == self.faucet_mac):
             in_port = pkt_meta.port.number
             vid = self._vlan_vid(vlan, in_port)
             echo_reply = valve_packet.echo_reply(
                 self.faucet_mac, pkt_meta.eth_src,
                 vid, dst_ip, src_ip, icmp_pkt.data)
             ofmsgs.append(
                 valve_of.packetout(in_port, echo_reply.data))
     return ofmsgs
Esempio n. 11
0
    def lacp_handler(self, pkt_meta):
        """Handle a LACP packet.

        We are a currently a passive, non-aggregateable LACP partner.

        Args:
            pkt_meta (PacketMeta): packet for control plane.
        Returns:
            list: OpenFlow messages, if any.
        """
        # TODO: ensure config consistent between LAG ports.
        ofmsgs = []
        if (pkt_meta.eth_dst == valve_packet.SLOW_PROTOCOL_MULTICAST
                and pkt_meta.eth_type == valve_of.ether.ETH_TYPE_SLOW
                and pkt_meta.port.lacp):
            pkt_meta.reparse_all()
            lacp_pkt = valve_packet.parse_lacp_pkt(pkt_meta.pkt)
            if lacp_pkt:
                last_lacp_up = pkt_meta.port.dyn_lacp_up
                pkt_meta.port.dyn_last_lacp_pkt = lacp_pkt
                pkt_meta.port.dyn_lacp_up = lacp_pkt.actor_state_synchronization
                pkt_meta.port.dyn_lacp_updated_time = time.time()
                if last_lacp_up != pkt_meta.port.dyn_lacp_up:
                    self.logger.info(
                        'LACP state change from %s to %s on %s to %s LAG %u' %
                        (last_lacp_up, pkt_meta.port.dyn_lacp_up,
                         pkt_meta.port, lacp_pkt.actor_system,
                         pkt_meta.port.lacp))
                    if pkt_meta.port.dyn_lacp_up:
                        ofmsgs.extend(self.lacp_up(pkt_meta.port))
                pkt = valve_packet.lacp_reqreply(
                    pkt_meta.vlan.faucet_mac, pkt_meta.vlan.faucet_mac,
                    pkt_meta.port.lacp, pkt_meta.port.number,
                    lacp_pkt.actor_system, lacp_pkt.actor_key,
                    lacp_pkt.actor_port, lacp_pkt.actor_system_priority,
                    lacp_pkt.actor_port_priority,
                    lacp_pkt.actor_state_defaulted,
                    lacp_pkt.actor_state_expired, lacp_pkt.actor_state_timeout,
                    lacp_pkt.actor_state_collecting,
                    lacp_pkt.actor_state_distributing,
                    lacp_pkt.actor_state_aggregation,
                    lacp_pkt.actor_state_synchronization,
                    lacp_pkt.actor_state_activity)
                ofmsgs.append(
                    valve_of.packetout(pkt_meta.port.number, pkt.data))
        return ofmsgs
Esempio n. 12
0
 def flood_pkt(self, packet_builder, multi_out=True, *args):
     ofmsgs = []
     for vid, ports in (
             (self.vid, self.tagged_flood_ports(False)),
             (None, self.untagged_flood_ports(False))):
         if ports:
             pkt = packet_builder(vid, *args)
             exclude_ports = self.exclude_same_lag_member_ports()
             running_port_nos = [
                 port.number for port in ports if port.running() and port not in exclude_ports]
             if running_port_nos:
                 random.shuffle(running_port_nos)
                 if multi_out:
                     ofmsgs.append(valve_of.packetouts(running_port_nos, pkt.data))
                 else:
                     ofmsgs.extend(
                         [valve_of.packetout(port_no, pkt.data) for port_no in running_port_nos])
     return ofmsgs
Esempio n. 13
0
    def send_lldp_beacons(self):
        """Called periodically to send LLDP beacon packets."""
        # TODO: the beacon service should be able to send configurable TLVs.
        # TODO: the beacon service is specifically NOT to discover topology.
        # It is intended to facilitate physical troubleshooting (e.g.
        # a standard cable tester can display OF port information)
        # A seperate system will be used to probe link/neighbor activity,
        # addressing issues such as authenticity of the probes.
        ofmsgs = []
        if self.dp.lldp_beacon_ports:
            now = time.time()
            beacons_sent = 0
            cutoff_beacon_time = now - self.dp.lldp_beacon['send_interval']
            ttl = self.dp.lldp_beacon['send_interval'] * 3
            for port in self.dp.lldp_beacon_ports:
                if (port.dyn_last_lldp_beacon_time is None or
                        port.dyn_last_lldp_beacon_time < cutoff_beacon_time):
                    lldp_beacon = port.lldp_beacon
                    chassis_id = str(port.native_vlan.faucet_mac)
                    org_tlvs = []
                    for org_tlv in lldp_beacon['org_tlvs']:
                        org_tlvs.append((org_tlv['oui'], org_tlv['subtype'],
                                         org_tlv['info']))
                    # if the port doesn't have a system name set, default to
                    # using the system name from the dp
                    if lldp_beacon['system_name'] is None:
                        lldp_beacon['system_name'] = self.dp.lldp_beacon[
                            'system_name']

                    lldp_beacon_pkt = valve_packet.lldp_beacon(
                        port.native_vlan.faucet_mac,
                        chassis_id,
                        port.number,
                        ttl,
                        org_tlvs=org_tlvs,
                        system_name=lldp_beacon['system_name'],
                        port_descr=lldp_beacon['port_descr'])
                    ofmsgs.append(
                        valve_of.packetout(port.number, lldp_beacon_pkt.data))
                    port.dyn_last_lldp_beacon_time = now
                    beacons_sent += 1
                    if beacons_sent == self.dp.lldp_beacon['max_per_interval']:
                        break
        return ofmsgs
Esempio n. 14
0
 def flood_pkt(self, packet_builder, multi_out=True, *args):
     ofmsgs = []
     for vid, ports in (
             (self.vid, self.tagged_flood_ports(False)),
             (None, self.untagged_flood_ports(False))):
         if ports:
             pkt = packet_builder(vid, *args)
             exclude_ports = self.exclude_same_lag_member_ports()
             running_ports = [
                 port for port in ports if port.running() and port not in exclude_ports]
             random.shuffle(running_ports)
             if multi_out:
                 ofmsgs.append(valve_of.packetouts(
                     [port.number for port in running_ports], pkt.data))
             else:
                 ofmsgs.extend(
                     [valve_of.packetout(port.number, pkt.data)
                      for port in running_ports])
     return ofmsgs
Esempio n. 15
0
 def flood_pkt(self, packet_builder, multi_out=True, *args):
     """Return Packet-out actions via flooding"""
     ofmsgs = []
     for vid, ports in (
             (self.vid, self.tagged_flood_ports(False)),
             (None, self.untagged_flood_ports(False))):
         if ports:
             pkt = packet_builder(vid, *args)
             exclude_ports = self.excluded_lag_ports()
             running_port_nos = [
                 port.number for port in ports if port.running() and port not in exclude_ports]
             if running_port_nos:
                 random.shuffle(running_port_nos)
                 if multi_out:
                     ofmsgs.append(valve_of.packetouts(running_port_nos, pkt.data))
                 else:
                     ofmsgs.extend(
                         [valve_of.packetout(port_no, pkt.data) for port_no in running_port_nos])
     return ofmsgs
Esempio n. 16
0
 def _flood_stack_links(self, pkt_builder, vlan, multi_out=True, *args):
     """Return flood packet-out actions to stack ports for gw resolving"""
     ofmsgs = []
     if isinstance(self.switch_manager, ValveSwitchStackManagerBase):
         ports = self.switch_manager._stack_flood_ports()
         if ports:
             running_port_nos = [
                 port.number for port in ports if port.running()
             ]
             pkt = pkt_builder(vlan.vid, *args)
             if running_port_nos:
                 random.shuffle(running_port_nos)
                 if multi_out:
                     ofmsgs.append(
                         valve_of.packetouts(running_port_nos, pkt.data))
                 else:
                     ofmsgs.extend([
                         valve_of.packetout(port_no, pkt.data)
                         for port_no in running_port_nos
                     ])
     return ofmsgs
Esempio n. 17
0
 def pkt_out_port(self, packet_builder, port, *args):
     vid = None
     if self.port_is_tagged(port):
         vid = self.vid
     pkt = packet_builder(vid, *args)
     return valve_of.packetout(port.number, pkt.data)
Esempio n. 18
0
 def _control_plane_icmpv6_handler(self, pkt_meta, ipv6_pkt):
     ofmsgs = []
     if not pkt_meta.packet_complete():
         return ofmsgs
     src_ip = ipaddress.IPv6Address(btos(ipv6_pkt.src))
     dst_ip = ipaddress.IPv6Address(btos(ipv6_pkt.dst))
     vlan = pkt_meta.vlan
     if vlan.ip_in_vip_subnet(src_ip):
         # Must be ICMPv6 and have no extended headers.
         if ipv6_pkt.nxt != valve_of.inet.IPPROTO_ICMPV6:
             return ofmsgs
         if ipv6_pkt.ext_hdrs:
             return ofmsgs
         # Explicitly ignore messages to all notes.
         if dst_ip == valve_packet.IPV6_ALL_NODES:
             return ofmsgs
         pkt_meta.reparse_ip(self.ETH_TYPE, payload=32)
         icmpv6_pkt = pkt_meta.pkt.get_protocol(icmpv6.icmpv6)
         if icmpv6_pkt is None:
             return ofmsgs
         icmpv6_type = icmpv6_pkt.type_
         if (ipv6_pkt.hop_limit != valve_packet.IPV6_MAX_HOP_LIM and
                 icmpv6_type != icmpv6.ICMPV6_ECHO_REQUEST):
             return ofmsgs
         port = pkt_meta.port
         vid = self._vlan_vid(vlan, port)
         eth_src = pkt_meta.eth_src
         if icmpv6_type == icmpv6.ND_NEIGHBOR_SOLICIT:
             solicited_ip = btos(icmpv6_pkt.data.dst)
             if vlan.is_faucet_vip(ipaddress.ip_address(solicited_ip)):
                 ofmsgs.extend(
                     self._add_host_fib_route(vlan, src_ip))
                 ofmsgs.extend(self._update_nexthop(
                     vlan, port, eth_src, src_ip))
                 nd_reply = valve_packet.nd_advert(
                     vid, vlan.faucet_mac, eth_src,
                     solicited_ip, src_ip)
                 ofmsgs.append(
                     valve_of.packetout(port.number, nd_reply.data))
                 self.logger.info(
                     'Responded to ND solicit for %s to %s (%s) on VLAN %u' % (
                         solicited_ip, src_ip, eth_src, vlan.vid))
         elif icmpv6_type == icmpv6.ND_NEIGHBOR_ADVERT:
             target_ip = btos(icmpv6_pkt.data.dst)
             if vlan.ip_in_vip_subnet(ipaddress.ip_address(target_ip)):
                 ofmsgs.extend(self._update_nexthop(
                     vlan, port, eth_src, target_ip))
                 self.logger.info(
                     'ND advert %s (%s) on VLAN %u' % (
                         target_ip, eth_src, vlan.vid))
         elif icmpv6_type == icmpv6.ND_ROUTER_SOLICIT:
             link_local_vips, other_vips = self._link_and_other_vips(vlan)
             for vip in link_local_vips:
                 if src_ip in vip.network:
                     ofmsgs.extend(
                         self._add_host_fib_route(vlan, src_ip))
                     ofmsgs.extend(self._update_nexthop(
                         vlan, port, eth_src, src_ip))
                     ra_advert = valve_packet.router_advert(
                         vlan, vid, vlan.faucet_mac, eth_src,
                         vip.ip, src_ip, other_vips)
                     ofmsgs.append(
                         valve_of.packetout(port.number, ra_advert.data))
                     self.logger.info(
                         'Responded to RS solicit from %s (%s) to VIP %s on VLAN %u' % (
                             src_ip, eth_src, vip, vlan.vid))
                     break
         elif icmpv6_type == icmpv6.ICMPV6_ECHO_REQUEST:
             if (vlan.from_connected_to_vip(src_ip, dst_ip) and
                     pkt_meta.eth_dst == vlan.faucet_mac):
                 icmpv6_echo_reply = valve_packet.icmpv6_echo_reply(
                     vid, vlan.faucet_mac, eth_src,
                     dst_ip, src_ip, ipv6_pkt.hop_limit,
                     icmpv6_pkt.data.id, icmpv6_pkt.data.seq,
                     icmpv6_pkt.data.data)
                 ofmsgs.append(
                     valve_of.packetout(port.number, icmpv6_echo_reply.data))
     return ofmsgs
Esempio n. 19
0
File: vlan.py Progetto: nfz1/faucet
 def pkt_out_port(self, packet_builder, port, *args):
     vid = None
     if self.port_is_tagged(port):
         vid = self.vid
     pkt = packet_builder(vid, *args)
     return valve_of.packetout(port.number, pkt.data)