コード例 #1
0
ファイル: valve_route.py プロジェクト: pablomguevara/faucet
 def _control_plane_icmpv6_handler(self, now, pkt_meta, ipv6_pkt):
     ofmsgs = []
     if not pkt_meta.packet_complete():
         return ofmsgs
     # 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
     dst_ip = ipaddress.IPv6Address(btos(ipv6_pkt.dst))
     # Explicitly ignore messages to all notes.
     if dst_ip == valve_packet.IPV6_ALL_NODES:
         return ofmsgs
     src_ip = ipaddress.IPv6Address(btos(ipv6_pkt.src))
     vlan = pkt_meta.vlan
     if not vlan.ip_in_vip_subnet(src_ip):
         return ofmsgs
     pkt_meta.reparse_ip(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
     if icmpv6_type in self._icmpv6_handlers:
         ofmsgs = self._icmpv6_handlers[icmpv6_type](self, now, pkt_meta,
                                                     ipv6_pkt, icmpv6_pkt,
                                                     src_ip, dst_ip)
     return ofmsgs
コード例 #2
0
ファイル: valve_route.py プロジェクト: JedS6391/faucet
 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
コード例 #3
0
    def _bgp_route_handler(self, path_change, vlan):
        """Handle a BGP change event.

        Args:
            path_change (ryu.services.protocols.bgp.bgpspeaker.EventPrefix): path change
            vlan (vlan): Valve VLAN this path change was received for.
        """
        prefix = ipaddress.ip_network(btos(path_change.prefix))
        nexthop = ipaddress.ip_address(btos(path_change.nexthop))
        withdraw = path_change.is_withdraw
        flowmods = []
        if not self._valves or vlan.dp_id not in self._valves:
            return
        valve = self._valves[vlan.dp_id]
        if vlan.is_faucet_vip(nexthop):
            self.logger.error('BGP nexthop %s for prefix %s cannot be us',
                              nexthop, prefix)
            return
        if vlan.ip_in_vip_subnet(nexthop) is None:
            self.logger.error(
                'BGP nexthop %s for prefix %s is not a connected network',
                nexthop, prefix)
            return

        if withdraw:
            self.logger.info('BGP withdraw %s nexthop %s', prefix, nexthop)
            flowmods = valve.del_route(vlan, prefix)
        else:
            self.logger.info('BGP add %s nexthop %s', prefix, nexthop)
            flowmods = valve.add_route(vlan, nexthop, prefix)
        if flowmods:
            self._send_flow_msgs(vlan.dp_id, flowmods)
コード例 #4
0
ファイル: vlan.py プロジェクト: bedcrb/faucet
    def __init__(self, _id, dp_id, conf=None):
        super(VLAN, self).__init__(_id, conf)
        self.dp_id = dp_id
        self.tagged = []
        self.untagged = []
        self.dyn_host_cache = {}
        self.dyn_faucet_vips_by_ipv = collections.defaultdict(list)
        self.dyn_routes_by_ipv = collections.defaultdict(dict)
        self.dyn_neigh_cache_by_ipv = collections.defaultdict(dict)
        self.dyn_ipvs = []

        if self.faucet_vips:
            self.faucet_vips = [
                ipaddress.ip_interface(btos(ip)) for ip in self.faucet_vips
            ]
            for faucet_vip in self.faucet_vips:
                self.dyn_faucet_vips_by_ipv[faucet_vip.version].append(
                    faucet_vip)
            self.dyn_ipvs = list(self.dyn_faucet_vips_by_ipv.keys())

        if self.bgp_as:
            assert self.bgp_port
            assert ipaddress.IPv4Address(btos(self.bgp_routerid))
            for neighbor_ip in self.bgp_neighbor_addresses:
                assert ipaddress.ip_address(btos(neighbor_ip))
            assert self.bgp_neighbor_as

        if self.routes:
            self.routes = [route['route'] for route in self.routes]
            for route in self.routes:
                ip_gw = ipaddress.ip_address(btos(route['ip_gw']))
                ip_dst = ipaddress.ip_network(btos(route['ip_dst']))
                assert ip_gw.version == ip_dst.version
                self.dyn_routes_by_ipv[ip_gw.version][ip_dst] = ip_gw
コード例 #5
0
ファイル: valve_route.py プロジェクト: thaihust/faucet
    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
コード例 #6
0
 def _control_plane_arp_handler(self, pkt_meta):
     ofmsgs = []
     if not pkt_meta.packet_complete():
         return ofmsgs
     pkt_meta.reparse_ip()
     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
         if opcode == arp.ARP_REQUEST:
             ofmsgs.extend(
                 self._add_host_fib_route(vlan, src_ip, blackhole=False))
             ofmsgs.extend(self._update_nexthop(vlan, port, eth_src,
                                                src_ip))
             ofmsgs.append(
                 vlan.pkt_out_port(valve_packet.arp_reply, port,
                                   vlan.faucet_mac, eth_src, dst_ip,
                                   src_ip))
             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
コード例 #7
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
コード例 #8
0
 def reparse_ip(self, payload=0):
     """Reparse packet with specified IP header type and optionally payload."""
     if self.eth_type in self.ETH_TYPES_PARSERS:
         header_size = self.MIN_ETH_TYPE_PKT_SIZE[self.eth_type]
         ip_ver, ip_parseable, pkt_parser = self.ETH_TYPES_PARSERS[
             self.eth_type]
         if ip_ver is not None:
             if ip_ver != self.ip_ver():
                 return
             if self.vlan is not None and self.vlan.minimum_ip_size_check:
                 if len(self.data) < header_size:
                     return
             ip_header_data = self.data[ETH_VLAN_HEADER_SIZE:]
             if ip_parseable is not None and not ip_parseable(
                     ip_header_data):
                 return
         parse_limit = header_size + payload
         self.reparse(parse_limit)
         self.l3_pkt = self.pkt.get_protocol(pkt_parser)
         if self.l3_pkt:
             if hasattr(self.l3_pkt, 'src'):
                 self.l3_src = self.l3_pkt.src
                 self.l3_dst = self.l3_pkt.dst
             elif hasattr(self.l3_pkt, 'src_ip'):
                 self.l3_src = self.l3_pkt.src_ip
                 self.l3_dst = self.l3_pkt.dst_ip
             self.l3_src = ipaddress.ip_address(valve_util.btos(
                 self.l3_src))
             self.l3_dst = ipaddress.ip_address(valve_util.btos(
                 self.l3_dst))
コード例 #9
0
ファイル: vlan.py プロジェクト: nfz1/faucet
    def check_config(self):
        super(VLAN, self).check_config()
        assert self.vid_valid(self.vid), 'invalid VID %s' % self.vid
        assert netaddr.valid_mac(
            self.faucet_mac), 'invalid MAC address %s' % self.faucet_mac

        if self.faucet_vips:
            try:
                self.faucet_vips = [
                    ipaddress.ip_interface(btos(ip)) for ip in self.faucet_vips
                ]
            except (ValueError, AttributeError, TypeError) as err:
                assert False, 'Invalid IP address in faucet_vips: %s' % err
            for faucet_vip in self.faucet_vips:
                self.dyn_faucet_vips_by_ipv[faucet_vip.version].append(
                    faucet_vip)
            self.dyn_ipvs = list(self.dyn_faucet_vips_by_ipv.keys())

        if self.bgp_as:
            assert self.bgp_port
            assert ipaddress.IPv4Address(btos(self.bgp_routerid))
            for neighbor_ip in self.bgp_neighbor_addresses:
                assert ipaddress.ip_address(btos(neighbor_ip))
            assert self.bgp_neighbor_as

        if self.routes:
            try:
                self.routes = [route['route'] for route in self.routes]
                for route in self.routes:
                    try:
                        ip_gw = ipaddress.ip_address(btos(route['ip_gw']))
                        ip_dst = ipaddress.ip_network(btos(route['ip_dst']))
                    except (ValueError, AttributeError, TypeError) as err:
                        assert False, 'Invalid IP address in route: %s' % err
                    assert ip_gw.version == ip_dst.version
                    self.dyn_routes_by_ipv[ip_gw.version][ip_dst] = ip_gw
            except KeyError:
                assert False, 'missing route config'
            except TypeError:
                assert False, '%s is not a valid routes value' % self.routes
        if self.acl_in and self.acls_in:
            assert False, 'found both acl_in and acls_in, use only acls_in'
        if self.acl_in and not isinstance(self.acl_in, list):
            self.acls_in = [
                self.acl_in,
            ]
            self.acl_in = None
        if self.acls_in:
            for acl in self.acls_in:
                assert isinstance(acl,
                                  (int, str)), 'acl names must be int or str'
コード例 #10
0
ファイル: valve_route.py プロジェクト: JedS6391/faucet
 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
コード例 #11
0
 def _nd_advert_handler(self, now, pkt_meta, _ipv6_pkt, icmpv6_pkt, _src_ip, _dst_ip):
     ofmsgs = []
     target_ip = ipaddress.ip_address(btos(icmpv6_pkt.data.dst))
     vlan = pkt_meta.vlan
     if vlan.ip_in_vip_subnet(target_ip):
         ofmsgs.extend(self._update_nexthop(
             now, vlan, pkt_meta.port, pkt_meta.eth_src, target_ip))
         self.logger.info(
             'ND advert %s (%s) on VLAN %u' % (
                 target_ip, pkt_meta.eth_src, vlan.vid))
     return ofmsgs
コード例 #12
0
ファイル: valve_route.py プロジェクト: lantz/faucet2
 def control_plane_handler(self, now, pkt_meta):
     ipv4_pkt = pkt_meta.pkt.get_protocol(ipv4.ipv4)
     if ipv4_pkt is None:
         return self._control_plane_arp_handler(now, pkt_meta)
     icmp_replies = self._control_plane_icmp_handler(pkt_meta, ipv4_pkt)
     if icmp_replies:
         return icmp_replies
     dst_ip = ipaddress.IPv4Address(btos(ipv4_pkt.dst))
     vlan = pkt_meta.vlan
     return self._proactive_resolve_neighbor(now, self._routed_vlans(vlan),
                                             dst_ip)
コード例 #13
0
 def control_plane_handler(self, pkt_meta):
     pkt = pkt_meta.pkt
     ipv6_pkt = pkt.get_protocol(ipv6.ipv6)
     if ipv6_pkt is not None:
         icmp_replies = self._control_plane_icmpv6_handler(
             pkt_meta, ipv6_pkt)
         if icmp_replies:
             return icmp_replies
         dst_ip = ipaddress.IPv6Address(btos(ipv6_pkt.dst))
         return self._proactive_resolve_neighbor(
             self._routed_vlans(pkt_meta.vlan), dst_ip)
     return []
コード例 #14
0
ファイル: valve_route.py プロジェクト: JedS6391/faucet
 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
コード例 #15
0
ファイル: valve_route.py プロジェクト: fortitudepub/faucet
 def _nd_advert_handler(self, now, pkt_meta, _ipv6_pkt, icmpv6_pkt, _src_ip, _dst_ip):
     ofmsgs = []
     if isinstance(icmpv6_pkt.data, icmpv6.nd_neighbor):
         target_ip = ipaddress.ip_address(btos(icmpv6_pkt.data.dst))
         vlan = pkt_meta.vlan
         if vlan.ip_in_vip_subnet(target_ip):
             if self._stateful_gw(vlan, target_ip):
                 ofmsgs.extend(self._update_nexthop(
                     now, vlan, pkt_meta.port, pkt_meta.eth_src, target_ip))
             self.logger.info(
                 'Received ND advert for %s from %s' % (
                     target_ip, pkt_meta.log()))
     return ofmsgs
コード例 #16
0
    def __init__(self, _id, dp_id, conf=None):
        if conf is None:
            conf = {}
        self._id = _id
        self.dp_id = dp_id
        self.update(conf)
        self.set_defaults()
        self._id = _id
        self.tagged = []
        self.untagged = []
        self.dyn_ipv4_routes = {}
        self.dyn_ipv6_routes = {}
        self.dyn_arp_cache = {}
        self.dyn_nd_cache = {}
        self.dyn_host_cache = {}

        if self.faucet_vips:
            self.faucet_vips = [
                ipaddress.ip_interface(btos(ip)) for ip in self.faucet_vips
            ]

        if self.bgp_as:
            assert self.bgp_port
            assert ipaddress.IPv4Address(btos(self.bgp_routerid))
            for neighbor_ip in self.bgp_neighbor_addresses:
                assert ipaddress.ip_address(btos(neighbor_ip))
            assert self.bgp_neighbor_as

        if self.routes:
            self.routes = [route['route'] for route in self.routes]
            for route in self.routes:
                ip_gw = ipaddress.ip_address(btos(route['ip_gw']))
                ip_dst = ipaddress.ip_network(btos(route['ip_dst']))
                assert ip_gw.version == ip_dst.version
                if ip_gw.version == 4:
                    self.ipv4_routes[ip_dst] = ip_gw
                else:
                    self.ipv6_routes[ip_dst] = ip_gw
コード例 #17
0
ファイル: valve_packet.py プロジェクト: essobi/faucet
def ipv6_solicited_node_from_ucast(ucast):
    """Return IPv6 solicited node multicast address from IPv6 unicast address.

    See RFC 3513 section 2.7.1.

    Args:
       ucast (ipaddress.IPv6Address): IPv6 unicast address.
    Returns:
       ipaddress.IPv6Address: IPv6 solicited node multicast address.
    """
    link_mcast_prefix = ipaddress.ip_interface(btos('ff02::1:ff00:0/104'))
    mcast_bytes = link_mcast_prefix.packed[:13] + ucast.packed[-3:]
    link_mcast = ipaddress.IPv6Address(mcast_bytes)
    return link_mcast
コード例 #18
0
    def check_config(self):
        super(VLAN, self).check_config()
        assert self.vid_valid(self.vid), 'invalid VID %s' % self.vid
        assert netaddr.valid_mac(self.faucet_mac), 'invalid MAC address %s' % self.faucet_mac

        if self.faucet_vips:
            try:
                self.faucet_vips = [
                    ipaddress.ip_interface(btos(ip)) for ip in self.faucet_vips]
            except (ValueError, AttributeError, TypeError) as err:
                assert False, 'Invalid IP address in faucet_vips: %s' % err
            for faucet_vip in self.faucet_vips:
                self.dyn_faucet_vips_by_ipv[faucet_vip.version].append(
                    faucet_vip)
            self.dyn_ipvs = list(self.dyn_faucet_vips_by_ipv.keys())

        if self.bgp_as:
            assert self.bgp_port
            assert ipaddress.IPv4Address(btos(self.bgp_routerid))
            for neighbor_ip in self.bgp_neighbor_addresses:
                assert ipaddress.ip_address(btos(neighbor_ip))
            assert self.bgp_neighbor_as

        if self.routes:
            try:
                self.routes = [route['route'] for route in self.routes]
                for route in self.routes:
                    try:
                        ip_gw = ipaddress.ip_address(btos(route['ip_gw']))
                        ip_dst = ipaddress.ip_network(btos(route['ip_dst']))
                    except (ValueError, AttributeError, TypeError) as err:
                        assert False, 'Invalid IP address in route: %s' % err
                    assert ip_gw.version == ip_dst.version
                    self.dyn_routes_by_ipv[ip_gw.version][ip_dst] = ip_gw
            except KeyError:
                assert False, 'missing route config'
コード例 #19
0
 def _nd_solicit_handler(self, now, pkt_meta, _ipv6_pkt, icmpv6_pkt, src_ip, _dst_ip):
     ofmsgs = []
     solicited_ip = btos(icmpv6_pkt.data.dst)
     vlan = pkt_meta.vlan
     if vlan.is_faucet_vip(ipaddress.ip_address(solicited_ip)):
         ofmsgs.extend(
             self._add_host_fib_route(vlan, src_ip, blackhole=False))
         ofmsgs.extend(self._update_nexthop(
             now, vlan, pkt_meta.port, pkt_meta.eth_src, src_ip))
         ofmsgs.append(
             vlan.pkt_out_port(
                 valve_packet.nd_advert, pkt_meta.port,
                 vlan.faucet_mac, pkt_meta.eth_src,
                 solicited_ip, src_ip))
         self.logger.info(
             'Responded to ND solicit for %s to %s (%s) on VLAN %u' % (
                 solicited_ip, src_ip, pkt_meta.eth_src, vlan.vid))
     return ofmsgs
コード例 #20
0
ファイル: valve_route.py プロジェクト: thaihust/faucet
    def add_host_fib_route_from_pkt(self, pkt_meta):
        """Add a host FIB route given packet from host.

        Args:
            pkt_meta (PacketMeta): received packet.
        Returns:
            list: OpenFlow messages.
        """
        ip_pkt = self._ip_pkt(pkt_meta.pkt)
        ofmsgs = []
        if ip_pkt:
            src_ip = ipaddress.ip_address(btos(ip_pkt.src))
            if src_ip and pkt_meta.vlan.ip_in_vip_subnet(src_ip):
                ofmsgs.extend(
                    self._add_host_fib_route(pkt_meta.vlan, src_ip))
                ofmsgs.extend(self._update_nexthop(
                    pkt_meta.vlan, pkt_meta.port, pkt_meta.eth_src, src_ip))
        return ofmsgs
コード例 #21
0
ファイル: valve_route.py プロジェクト: fortitudepub/faucet
 def _nd_solicit_handler(self, now, pkt_meta, _ipv6_pkt, icmpv6_pkt, src_ip, _dst_ip):
     ofmsgs = []
     if isinstance(icmpv6_pkt.data, icmpv6.nd_neighbor):
         solicited_ip = ipaddress.ip_address(btos(icmpv6_pkt.data.dst))
         vlan = pkt_meta.vlan
         if vlan.is_faucet_vip(solicited_ip):
             if self._stateful_gw(vlan, src_ip):
                 ofmsgs.extend(
                     self._add_host_fib_route(vlan, src_ip, blackhole=False))
                 ofmsgs.extend(self._update_nexthop(
                     now, vlan, pkt_meta.port, pkt_meta.eth_src, src_ip))
             ofmsgs.append(
                 vlan.pkt_out_port(
                     valve_packet.nd_advert, pkt_meta.port,
                     vlan.faucet_mac, pkt_meta.eth_src,
                     solicited_ip, src_ip))
             self.logger.info(
                 'Responded to ND solicit for %s from %s' % (
                     solicited_ip, pkt_meta.log()))
     return ofmsgs
コード例 #22
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(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
         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,
                                              blackhole=False))
                 ofmsgs.extend(
                     self._update_nexthop(vlan, port, eth_src, src_ip))
                 ofmsgs.append(
                     vlan.pkt_out_port(valve_packet.nd_advert, port,
                                       vlan.faucet_mac, eth_src,
                                       solicited_ip, src_ip))
                 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 = ipaddress.ip_address(btos(icmpv6_pkt.data.dst))
             if vlan.ip_in_vip_subnet(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,
                                                  blackhole=False))
                     ofmsgs.extend(
                         self._update_nexthop(vlan, port, eth_src, src_ip))
                     ofmsgs.append(
                         vlan.pkt_out_port(valve_packet.router_advert, port,
                                           vlan.faucet_mac, eth_src, vip.ip,
                                           src_ip, other_vips))
                     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):
                 ofmsgs.append(
                     vlan.pkt_out_port(valve_packet.icmpv6_echo_reply, port,
                                       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))
     return ofmsgs
コード例 #23
0
 def _nd_solicit_handler(self, now, pkt_meta, _ipv6_pkt, icmpv6_pkt):
     ofmsgs = []
     solicited_ip = ipaddress.ip_address(btos(icmpv6_pkt.data.dst))
     ofmsgs.extend(self._resolve_vip_response(pkt_meta, solicited_ip, now))
     return ofmsgs
コード例 #24
0
 def _nd_advert_handler(self, now, pkt_meta, _ipv6_pkt, icmpv6_pkt):
     ofmsgs = []
     target_ip = ipaddress.ip_address(btos(icmpv6_pkt.data.dst))
     ofmsgs.extend(self._gw_advert(pkt_meta, target_ip, now))
     return ofmsgs
コード例 #25
0
ファイル: valve_packet.py プロジェクト: essobi/faucet
FAUCET_MAC = '0e:00:00:00:00:01'  # Default FAUCET MAC address

ETH_HEADER_SIZE = 14
ETH_VLAN_HEADER_SIZE = ETH_HEADER_SIZE + 4  # https://en.wikipedia.org/wiki/IEEE_802.1Q#Frame_format
IPV4_HEADER_SIZE = 20  # https://en.wikipedia.org/wiki/IPv4#Header
IPV6_HEADER_SIZE = 40  # https://en.wikipedia.org/wiki/IPv6_packet#Fixed_header
ARP_PKT_SIZE = 28  # https://en.wikipedia.org/wiki/Address_Resolution_Protocol#Packet_structure

SLOW_PROTOCOL_MULTICAST = slow.SLOW_PROTOCOL_MULTICAST
BRIDGE_GROUP_ADDRESS = bpdu.BRIDGE_GROUP_ADDRESS
BRIDGE_GROUP_MASK = 'ff:ff:ff:ff:ff:f0'
LLDP_MAC_NEAREST_BRIDGE = lldp.LLDP_MAC_NEAREST_BRIDGE
CISCO_SPANNING_GROUP_ADDRESS = '01:00:0c:cc:cc:cd'
IPV6_ALL_NODES_MCAST = '33:33:00:00:00:01'
IPV6_ALL_ROUTERS_MCAST = '33:33:00:00:00:02'
IPV6_LINK_LOCAL = ipaddress.IPv6Network(btos('fe80::/10'))
IPV6_ALL_NODES = ipaddress.IPv6Address(btos('ff02::1'))
IPV6_MAX_HOP_LIM = 255

LLDP_FAUCET_DP_ID = 1
LLDP_FAUCET_STACK_STATE = 2


def ipv4_parseable(ip_header_data):
    """Return True if an IPv4 packet we could parse."""
    # TODO: python library parsers are fragile
    # Perform sanity checking on the header to limit exposure of the parser
    ipv4_header = struct.unpack('!BBHHHBBH4s4s',
                                ip_header_data[:IPV4_HEADER_SIZE])
    header_size = (ipv4_header[0] & 0xf) * 32 / 8
    if header_size < IPV4_HEADER_SIZE:
コード例 #26
0
ファイル: vlan.py プロジェクト: lantz/faucet2
 def _check_ip_str(ip_str, ip_method=ipaddress.ip_address):
     try:
         return ip_method(btos(ip_str))
     except (ValueError, AttributeError, TypeError) as err:
         raise InvalidConfigError('Invalid IP address %s: %s' %
                                  (ip_str, err))
コード例 #27
0
ファイル: vlan.py プロジェクト: wackerly/faucet
    def check_config(self):
        super(VLAN, self).check_config()
        test_config_condition(not self.vid_valid(self.vid),
                              'invalid VID %s' % self.vid)
        test_config_condition(not netaddr.valid_mac(self.faucet_mac),
                              ('invalid MAC address %s' % self.faucet_mac))
        if self.max_hosts:
            if not self.proactive_arp_limit:
                self.proactive_arp_limit = 2 * self.max_hosts
            if not self.proactive_nd_limit:
                self.proactive_nd_limit = 2 * self.max_hosts
        if self.faucet_vips:
            try:
                self.faucet_vips = [
                    ipaddress.ip_interface(btos(ip)) for ip in self.faucet_vips
                ]
            except (ValueError, AttributeError, TypeError) as err:
                raise InvalidConfigError(
                    'Invalid IP address in faucet_vips: %s' % err)
            for faucet_vip in self.faucet_vips:
                self.dyn_faucet_vips_by_ipv[faucet_vip.version].append(
                    faucet_vip)
            self.dyn_ipvs = list(self.dyn_faucet_vips_by_ipv.keys())
        if self.bgp_neighbor_addresses or self.bgp_neighbour_addresses:
            neigh_addresses = set(self.bgp_neighbor_addresses +
                                  self.bgp_neighbour_addresses)
            try:
                self.bgp_neighbor_addresses = [
                    ipaddress.ip_address(btos(ip)) for ip in neigh_addresses
                ]
            except (ValueError, AttributeError, TypeError) as err:
                raise InvalidConfigError(
                    'Invalid IP address in bgp_neighbor_addresses: %s' % err)
            for bgp_neighbor_address in self.bgp_neighbor_addresses:
                self.dyn_bgp_neighbor_addresses_by_ipv[
                    bgp_neighbor_address.version].append(bgp_neighbor_address)
        if self.bgp_server_addresses:
            try:
                self.bgp_server_addresses = [
                    ipaddress.ip_address(btos(ip))
                    for ip in self.bgp_server_addresses
                ]
            except (ValueError, AttributeError, TypeError) as err:
                raise InvalidConfigError(
                    'Invalid IP address in bgp_server_addresses: %s' % err)
            for bgp_server_address in self.bgp_server_addresses:
                self.dyn_bgp_server_addresses_by_ipv[
                    bgp_server_address.version].append(bgp_server_address)
            self.dyn_bgp_ipvs = list(
                self.dyn_bgp_server_addresses_by_ipv.keys())

        if self.bgp_as:
            test_config_condition(not isinstance(self.bgp_port, int),
                                  ('BGP port must be %s not %s' %
                                   (int, type(self.bgp_port))))
            test_config_condition(
                self.bgp_connect_mode not in ('active', 'passive', 'both'),
                ('%s must be active, passive or both' % self.bgp_connect_mode))
            test_config_condition(
                not ipaddress.IPv4Address(btos(self.bgp_routerid)),
                ('%s is not a valid IPv4 address' % (self.bgp_routerid)))
            test_config_condition(not self.bgp_neighbor_as,
                                  'No BGP neighbor AS')
            test_config_condition(not self.bgp_neighbor_addresses,
                                  'No BGP neighbor addresses')
            neighbor_ips = self.bgp_neighbor_addresses
            test_config_condition(
                len(neighbor_ips) != len(self.bgp_neighbor_addresses),
                ('Neighbor IPs is not the same length as BGP neighbor addresses'
                 ))
            peer_versions = [ip.version for ip in neighbor_ips]
            test_config_condition(
                len(peer_versions) != 1 and self.bgp_connect_mode != 'active',
                ('if using multiple address families bgp_connect_mode must be active'
                 ))

        if self.routes:
            try:
                self.routes = [route['route'] for route in self.routes]
                for route in self.routes:
                    try:
                        ip_gw = ipaddress.ip_address(btos(route['ip_gw']))
                        ip_dst = ipaddress.ip_network(btos(route['ip_dst']))
                    except (ValueError, AttributeError, TypeError) as err:
                        raise InvalidConfigError(
                            'Invalid IP address in route: %s' % err)
                    test_config_condition(
                        ip_gw.version != ip_dst.version,
                        'ip_gw version does not match the ip_dst version')
                    self.add_route(ip_dst, ip_gw)
            except KeyError as err:
                raise InvalidConfigError('missing route config %s' % err)
            except TypeError:
                raise InvalidConfigError('%s is not a valid routes value' %
                                         self.routes)
        test_config_condition(
            self.acl_in and self.acls_in,
            'found both acl_in and acls_in, use only acls_in')
        if self.acl_in and not isinstance(self.acl_in, list):
            self.acls_in = [
                self.acl_in,
            ]
            self.acl_in = None
        if self.acls_in:
            for acl in self.acls_in:
                test_config_condition(not isinstance(acl, (int, str)),
                                      'acl names must be int or str')
コード例 #28
0
ファイル: valve_route.py プロジェクト: JedS6391/faucet
 def _host_from_faucet_vip(self, faucet_vip):
     max_prefixlen = faucet_vip.ip.max_prefixlen
     return ipaddress.ip_interface(
         btos('/'.join((faucet_vip.ip.exploded, str(max_prefixlen)))))
コード例 #29
0
FAUCET_MAC = '0e:00:00:00:00:01'  # Default FAUCET MAC address

ETH_HEADER_SIZE = 14
ETH_VLAN_HEADER_SIZE = ETH_HEADER_SIZE + 4  # https://en.wikipedia.org/wiki/IEEE_802.1Q#Frame_format
IPV4_HEADER_SIZE = 20  # https://en.wikipedia.org/wiki/IPv4#Header
IPV6_HEADER_SIZE = 40  # https://en.wikipedia.org/wiki/IPv6_packet#Fixed_header
ARP_PKT_SIZE = 28  # https://en.wikipedia.org/wiki/Address_Resolution_Protocol#Packet_structure

SLOW_PROTOCOL_MULTICAST = slow.SLOW_PROTOCOL_MULTICAST
BRIDGE_GROUP_ADDRESS = bpdu.BRIDGE_GROUP_ADDRESS
BRIDGE_GROUP_MASK = 'ff:ff:ff:ff:ff:f0'
LLDP_MAC_NEAREST_BRIDGE = lldp.LLDP_MAC_NEAREST_BRIDGE
CISCO_SPANNING_GROUP_ADDRESS = '01:00:0c:cc:cc:cd'
IPV6_ALL_NODES_MCAST = '33:33:00:00:00:01'
IPV6_ALL_ROUTERS_MCAST = '33:33:00:00:00:02'
IPV6_ALL_NODES = ipaddress.IPv6Address(valve_util.btos('ff02::1'))
IPV6_MAX_HOP_LIM = 255

LLDP_FAUCET_DP_ID = 1
LLDP_FAUCET_STACK_STATE = 2


def int_from_mac(mac):
    int_hi, int_lo = [int(i, 16) for i in mac.split(':')[-2:]]
    return (int_hi << 8) + int_lo


def int_in_mac(mac, to_int):
    int_mac = mac.split(':')[:4] + [
        '%x' % (to_int >> 8), '%x' % (to_int & 0xff)
    ]
コード例 #30
0
ファイル: vlan.py プロジェクト: lantz/faucet2
    def check_config(self):
        super(VLAN, self).check_config()
        test_config_condition(not self.vid_valid(self.vid),
                              'invalid VID %s' % self.vid)
        test_config_condition(not netaddr.valid_mac(self.faucet_mac),
                              ('invalid MAC address %s' % self.faucet_mac))

        test_config_condition(
            self.acl_in and self.acls_in,
            'found both acl_in and acls_in, use only acls_in')
        if self.acl_in and not isinstance(self.acl_in, list):
            self.acls_in = [
                self.acl_in,
            ]
            self.acl_in = None
        if self.acls_in:
            for acl in self.acls_in:
                test_config_condition(not isinstance(acl, (int, str)),
                                      'acl names must be int or str')

        if self.max_hosts:
            if not self.proactive_arp_limit:
                self.proactive_arp_limit = 2 * self.max_hosts
            if not self.proactive_nd_limit:
                self.proactive_nd_limit = 2 * self.max_hosts

        if self.faucet_vips:
            self.faucet_vips = frozenset([
                self._check_ip_str(ip_str, ip_method=ipaddress.ip_interface)
                for ip_str in self.faucet_vips
            ])

        if self.bgp_neighbor_addresses or self.bgp_neighbour_addresses:
            neigh_addresses = frozenset(self.bgp_neighbor_addresses +
                                        self.bgp_neighbour_addresses)
            self.bgp_neighbor_addresses = frozenset(
                [self._check_ip_str(ip_str) for ip_str in neigh_addresses])

        if self.bgp_server_addresses:
            self.bgp_server_addresses = frozenset([
                self._check_ip_str(ip_str)
                for ip_str in self.bgp_server_addresses
            ])
            for ipv in self.bgp_ipvs():
                test_config_condition(
                    len(self.bgp_server_addresses_by_ipv(ipv)) != 1,
                    'Only one BGP server address per IP version supported')

        if self.bgp_as:
            test_config_condition(not isinstance(self.bgp_port, int),
                                  ('BGP port must be %s not %s' %
                                   (int, type(self.bgp_port))))
            test_config_condition(self.bgp_connect_mode not in ('passive'),
                                  ('BGP connect mode %s must be passive' %
                                   self.bgp_connect_mode))
            test_config_condition(
                not ipaddress.IPv4Address(btos(self.bgp_routerid)),
                ('%s is not a valid IPv4 address' % (self.bgp_routerid)))
            test_config_condition(not self.bgp_neighbor_as,
                                  'No BGP neighbor AS')
            test_config_condition(not self.bgp_neighbor_addresses,
                                  'No BGP neighbor addresses')
            test_config_condition(
                len(self.bgp_neighbor_addresses) != len(
                    self.bgp_neighbor_addresses),
                ('Must be as many BGP neighbor addresses as BGP server addresses'
                 ))

        if self.routes:
            test_config_condition(not isinstance(self.routes, list),
                                  'invalid VLAN routes format')
            try:
                self.routes = [route['route'] for route in self.routes]
            except TypeError:
                raise InvalidConfigError('%s is not a valid routes value' %
                                         self.routes)
            except KeyError:
                pass
            for route in self.routes:
                test_config_condition(not isinstance(route, dict),
                                      'invalid VLAN route format')
                test_config_condition('ip_gw' not in route,
                                      'missing ip_gw in VLAN route')
                test_config_condition('ip_dst' not in route,
                                      'missing ip_dst in VLAN route')
                ip_gw = self._check_ip_str(route['ip_gw'])
                ip_dst = self._check_ip_str(route['ip_dst'],
                                            ip_method=ipaddress.ip_network)
                test_config_condition(
                    ip_gw.version != ip_dst.version,
                    'ip_gw version does not match the ip_dst version')
                self.add_route(ip_dst, ip_gw)