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): 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, self.faucet_mac, eth_src, solicited_ip, src_ip, ipv6_pkt.hop_limit) ofmsgs.append( valve_of.packetout(port.number, 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, port, eth_src, src_ip)) self.logger.info( 'ND advert %s (%s)', src_ip, eth_src) 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: ra_advert = valve_packet.router_advert( vid, self.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', src_ip, eth_src, vip) break 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( vid, self.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
def _control_plane_icmpv6_handler(self, pkt_meta, ipv6_pkt): 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 != 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: ofmsgs.extend(self._update_nexthop( vlan, port, eth_src, src_ip)) self.logger.info( 'ND advert %s (%s) on VLAN %u' % ( src_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