def _get_dhcp_port_arp_responder(self, lport): return arp_responder.ArpResponder( app=self, network_id=lport.lswitch.unique_key, interface_ip=lport.ip, interface_mac=lport.mac, )
def _remove_floatingip_arp_responder(self, floatingip): # install floatingip arp responder flow rules if netaddr.IPAddress(floatingip.get_ip_address()).version != 4: return arp_responder.ArpResponder(self, None, floatingip.get_ip_address(), floatingip.get_mac_address(), const.INGRESS_NAT_TABLE).remove()
def _create_arp_responder(self, mac): self._arp_responder = arp_responder.ArpResponder( self, None, const.METADATA_SERVICE_IP, mac ) self._arp_responder.add()
def _remove_floatingip_arp_responder(self, floatingip): # install floatingip arp responder flow rules if floatingip.floating_ip_address.version != n_const.IP_VERSION_4: return floating_lport = self._get_floating_lport(floatingip) arp_responder.ArpResponder(self, None, floatingip.floating_ip_address, floating_lport.mac, const.INGRESS_NAT_TABLE).remove()
def _remove_arp_responder(self, lport): if not self.is_install_arp_responder: return ip = lport.get_ip() if netaddr.IPAddress(ip).version != 4: return network_id = lport.get_external_value('local_network_id') arp_responder.ArpResponder(self.get_datapath(), network_id, ip).remove()
def _remove_arp_responder(self, lport): if not self.is_install_arp_responder: return if lport.get_device_owner() == common_const.DEVICE_OWNER_ROUTER_INTF: return ip = lport.get_ip() if netaddr.IPAddress(ip).version != 4: return network_id = lport.get_external_value('local_network_id') arp_responder.ArpResponder(self, network_id, ip).remove()
def _remove_arp_responder(self, host_ip, host_mac): # install host arp responder flow rules if netaddr.IPAddress(host_ip).version != n_const.IP_VERSION_4: return arp_responder.ArpResponder( self, None, host_ip, host_mac, const.INGRESS_NAT_TABLE).remove()
def _remove_l2_responders(self, lport): if not self.is_install_l2_responder: return ips = lport.ips network_id = lport.lswitch.unique_key for ip in ips: ip_version = ip.version if ip_version == common_const.IP_VERSION_4: arp_responder.ArpResponder(self, network_id, ip).remove() elif ip_version == common_const.IP_VERSION_6: nd_advertisers.NeighborAdvertiser(self, network_id, ip).remove()
def _delete_router_port(self, router, router_port): """ Handle the removal of a router interface from a router. Undoes the actions in #_add_new_router_port. :param router: The router on which the interface is removed :type router: LogicalRouter model object :param router_port: The router interface being removed :type router_port: RouterInterface model object """ LOG.info("Removing logical router interface = %s", router_port) local_network_id = router_port.lswitch.unique_key parser = self.parser ofproto = self.ofproto router_unique_key = router.unique_key ip = router_port.network.ip mac = router_port.mac # Delete rule for making packets go from L2_LOOKUP_TABLE # to L3_LOOKUP_TABLE match = parser.OFPMatch() match.set_metadata(local_network_id) match.set_dl_dst(os_ken_mac_lib.haddr_to_bin(mac)) self.mod_flow( table_id=const.L2_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_HIGH, match=match) # Delete ARP & ICMP responder for router interface if ip.version == common_const.IP_VERSION_4: arp_responder.ArpResponder(self, local_network_id, ip).remove() icmp_responder.ICMPResponder(self, ip, router_key=router_unique_key).remove() # Delete rule for packets whose destination is router interface. match = self._get_router_interface_match(router_unique_key, ip) self.mod_flow( table_id=const.L3_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_HIGH, match=match) # Delete rule for routing packets to subnet of this router port match = self._get_router_route_match(router_unique_key, router_port.network) self.mod_flow( table_id=const.L3_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_MEDIUM, match=match)
def _delete_router_port(self, router_port): LOG.info(_LI("Removing logical router interface = %s"), router_port) local_network_id = self.db_store.get_network_id( router_port.get_lswitch_id() ) parser = self.get_datapath().ofproto_parser ofproto = self.get_datapath().ofproto tunnel_key = router_port.get_tunnel_key() ip = router_port.get_ip() mac = router_port.get_mac() if netaddr.IPAddress(ip).version == 4: arp_responder.ArpResponder( self.get_datapath(), local_network_id, ip).remove() icmp_responder.ICMPResponder(self.get_datapath(), ip, mac).remove() match = parser.OFPMatch() match.set_metadata(local_network_id) self.mod_flow( datapath=self.get_datapath(), table_id=const.L3_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_MEDIUM, out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY, match=match) match = parser.OFPMatch() match.set_metadata(local_network_id) match.set_dl_dst(haddr_to_bin(mac)) self.mod_flow( datapath=self.get_datapath(), table_id=const.L2_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_HIGH, out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY, match=match) match = parser.OFPMatch() cookie = tunnel_key self.mod_flow( datapath=self.get_datapath(), cookie=cookie, cookie_mask=cookie, table_id=const.L3_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_MEDIUM, out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY, match=match)
def _add_l2_responders(self, lport): if not self.is_install_l2_responder: return ips = lport.ips network_id = lport.local_network_id mac = lport.mac for ip in ips: ip_version = ip.version if ip_version == common_const.IP_VERSION_4: arp_responder.ArpResponder(self, network_id, ip, mac).add() elif ip_version == common_const.IP_VERSION_6: nd_advertisers.NeighborAdvertiser(self, network_id, ip, mac).add()
def _get_arp_responder(self, floatingip): # ARP responder is placed in L2. This is needed to avoid the multicast # flow for provider network in L2 table. # The packet is egressed to EGRESS_TABLE so it can reach the provider # network. return arp_responder.ArpResponder( app=self, network_id=floatingip.floating_lport.lswitch.unique_key, interface_ip=floatingip.floating_lport.ip, interface_mac=floatingip.floating_lport.mac, table_id=const.L2_LOOKUP_TABLE, priority=const.PRIORITY_HIGH, goto_table_id=const.EGRESS_TABLE, source_port_key=floatingip.floating_lport.unique_key, )
def _uninstall_dhcp_port_responders(self, lport): ips_v4 = (ip for ip in lport.ips if ip.version == n_const.IP_VERSION_4) for ip in ips_v4: icmp_responder.ICMPResponder( app=self, network_id=lport.lswitch.unique_key, interface_ip=lport.ip, table_id=const.L2_LOOKUP_TABLE, ).remove() arp_responder.ArpResponder( app=self, network_id=lport.lswitch.unique_key, interface_ip=ip, interface_mac=lport.mac, ).remove()
def _delete_router_port(self, router, router_port): LOG.info("Removing logical router interface = %s", router_port) local_network_id = router_port.lswitch.unique_key parser = self.parser ofproto = self.ofproto router_unique_key = router.unique_key ip = router_port.network.ip mac = router_port.mac # Delete rule for making packets go from L2_LOOKUP_TABLE # to L3_LOOKUP_TABLE match = parser.OFPMatch() match.set_metadata(local_network_id) match.set_dl_dst(ryu_mac_lib.haddr_to_bin(mac)) self.mod_flow( table_id=const.L2_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_HIGH, match=match) # Delete ARP & ICMP responder for router interface if ip.version == common_const.IP_VERSION_4: self.router_port_rarp_cache.pop(mac, None) arp_responder.ArpResponder(self, local_network_id, ip).remove() icmp_responder.ICMPResponder(self, ip, router_key=router_unique_key).remove() # Delete rule for packets whose destination is router interface. match = self._get_router_interface_match(router_unique_key, ip) self.mod_flow( table_id=const.L3_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_HIGH, match=match) # Delete rule for routing packets to subnet of this router port match = self._get_router_route_match(router_unique_key, router_port.network.network, router_port.network.netmask) self.mod_flow( table_id=const.L3_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_MEDIUM, match=match)
def _add_new_router_port(self, router, router_port): LOG.info(_LI("Adding new logical router interface = %s"), router_port) local_network_id = self.db_store.get_network_id( router_port.get_lswitch_id()) datapath = self.get_datapath() parser = datapath.ofproto_parser ofproto = datapath.ofproto mac = router_port.get_mac() tunnel_key = router_port.get_tunnel_key() dst_ip = router_port.get_ip() # Add router ARP & ICMP responder for IPv4 Addresses is_ipv4 = netaddr.IPAddress(dst_ip).version == 4 if is_ipv4: arp_responder.ArpResponder(datapath, local_network_id, dst_ip, mac).add() icmp_responder.ICMPResponder(datapath, dst_ip, mac).add() # If router interface IP, send to output table if is_ipv4: match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP, metadata=local_network_id, ipv4_dst=dst_ip) else: match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IPV6, metadata=local_network_id, ipv6_dst=dst_ip) actions = [] actions.append(parser.OFPActionSetField(reg7=tunnel_key)) action_inst = self.get_datapath().ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions) goto_inst = parser.OFPInstructionGotoTable(const.EGRESS_TABLE) inst = [action_inst, goto_inst] self.mod_flow(datapath, inst=inst, table_id=const.L3_LOOKUP_TABLE, priority=const.PRIORITY_HIGH, match=match) # Add router ip match go to output table self._install_flow_send_to_output_table(local_network_id, tunnel_key, dst_ip) #add dst_mac=gw_mac l2 goto l3 flow match = parser.OFPMatch() match.set_metadata(local_network_id) match.set_dl_dst(haddr_to_bin(mac)) goto_inst = parser.OFPInstructionGotoTable(const.L3_LOOKUP_TABLE) inst = [goto_inst] self.mod_flow(self.get_datapath(), inst=inst, table_id=const.L2_LOOKUP_TABLE, priority=const.PRIORITY_HIGH, match=match) # Match all possible routeable traffic and send to proactive routing for port in router.get_ports(): if port.get_id() != router_port.get_id(): port_net_id = self.db_store.get_network_id( port.get_lswitch_id(), ) # From this router interface to all other interfaces self._add_subnet_send_to_proactive_routing( local_network_id, port.get_cidr_network(), port.get_cidr_netmask(), port.get_tunnel_key(), port_net_id, port.get_mac()) # From all the other interfaces to this new interface self._add_subnet_send_to_proactive_routing( port_net_id, router_port.get_cidr_network(), router_port.get_cidr_netmask(), tunnel_key, local_network_id, router_port.get_mac())
def _add_new_router_port(self, router, router_port): LOG.info("Adding new logical router interface = %r", router_port) local_network_id = router_port.lswitch.unique_key parser = self.parser ofproto = self.ofproto mac = router_port.mac router_unique_key = router.unique_key dst_ip = router_port.network.ip is_ipv4 = (netaddr.IPAddress(dst_ip).version == common_const.IP_VERSION_4) # Add rule for making packets go from L2_LOOKUP_TABLE # to L3_LOOKUP_TABLE match = parser.OFPMatch() match.set_metadata(local_network_id) match.set_dl_dst(ryu_mac_lib.haddr_to_bin(mac)) actions = [parser.OFPActionSetField(reg5=router_unique_key)] action_inst = parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions) goto_inst = parser.OFPInstructionGotoTable(const.L3_LOOKUP_TABLE) inst = [action_inst, goto_inst] self.mod_flow( inst=inst, table_id=const.L2_LOOKUP_TABLE, priority=const.PRIORITY_HIGH, match=match) # Add router ARP & ICMP responder for IPv4 Addresses if is_ipv4: self.router_port_rarp_cache[mac] = dst_ip arp_responder.ArpResponder(self, local_network_id, dst_ip, mac).add() icmp_responder.ICMPResponder(self, dst_ip, router_key=router_unique_key).add() # If router interface is not concrete, send to local controller. local # controller will create icmp unreachable mesage. A virtual router # interface will not be in local cache, as it doesn't have chassis # information. lport = self.db_store2.get_one(l2.LogicalPort(id=router_port.id)) if not lport: match = self._get_router_interface_match(router_unique_key, dst_ip) actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)] action_inst = parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions) self.mod_flow( inst=[action_inst], table_id=const.L3_LOOKUP_TABLE, priority=const.PRIORITY_HIGH, match=match) else: self._add_concrete_router_interface(lport, router=router) # Add rule for routing packets to subnet of this router port match = self._get_router_route_match(router_unique_key, router_port.network.network, router_port.network.netmask) self._add_subnet_send_to_route(match, local_network_id, router_port)
def _delete_router_port(self, router_port): LOG.info(_LI("Removing logical router interface = %s"), router_port) local_network_id = self.db_store.get_network_id( router_port.get_lswitch_id() ) parser = self.get_datapath().ofproto_parser ofproto = self.get_datapath().ofproto tunnel_key = router_port.get_tunnel_key() ip = router_port.get_ip() mac = router_port.get_mac() if netaddr.IPAddress(ip).version == 4: arp_responder.ArpResponder(self, local_network_id, ip).remove() icmp_responder.ICMPResponder(self, ip, mac).remove() match = parser.OFPMatch() match.set_metadata(local_network_id) self.mod_flow( datapath=self.get_datapath(), table_id=const.L3_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_MEDIUM, match=match) match = parser.OFPMatch() match.set_metadata(local_network_id) match.set_dl_dst(haddr_to_bin(mac)) self.mod_flow( datapath=self.get_datapath(), table_id=const.L2_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_HIGH, match=match) match = parser.OFPMatch() cookie = tunnel_key self.mod_flow( datapath=self.get_datapath(), cookie=cookie, cookie_mask=cookie, table_id=const.L3_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_MEDIUM, match=match) # Remove router port ip proactive flow if netaddr.IPAddress(router_port.get_ip()).version == 4: match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP, metadata=local_network_id, ipv4_dst=router_port.get_ip()) else: match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IPV6, metadata=local_network_id, ipv6_dst=router_port.get_ip()) self.mod_flow( datapath=self.get_datapath(), table_id=const.L3_PROACTIVE_LOOKUP_TABLE, command=ofproto.OFPFC_DELETE, priority=const.PRIORITY_HIGH, match=match)