def egress_src_dest_pairs_policy(self): policies = [] for src_dest_pair in self.nib.get_egress_src_dest_pairs(): (src_ip, dst_ip) = src_dest_pair # Convert dst_ip to its real form. First find out what the egress switch actually is: for ap in self.nib.alternate_paths(): if NetUtils.ip_in_network(dst_ip, ap["ithaca"]): switch = "ithaca" imaginary_net = ap["ithaca"] elif NetUtils.ip_in_network(dst_ip, ap["nyc"]): switch = "nyc" imaginary_net = ap["nyc"] real_net = self.nib.actual_net_for(switch) dst_host = NetUtils.host_of_ip(dst_ip, imaginary_net) new_dest_ip = NetUtils.ip_for_network(real_net, dst_host) # If it's not in the ARP cache, it already has an ARP request on the way so ignore it for now. if self.nib.learned_ip(new_dest_ip): direct_net_port = self.nib.port_for_ip(new_dest_ip) new_src_ip = self.nib.translate_alternate_net(src_ip) output_actions = SetIP4Src(new_src_ip) >> SetIP4Dst(new_dest_ip) >> Send(direct_net_port) policies.append( Filter(SwitchEq(self.nib.switch_to_dpid(switch)) & Policies.is_ip_from_to(src_ip, dst_ip)) >> output_actions ) return Union(policies)
def send_along_preferred_path(self, switch, src_ip, dst_ip, payload): # Get host from src_ip src_pref_net = self.nib.preferred_net(switch) src_host = NetUtils.host_of_ip(src_ip, self.nib.actual_net_for(switch)) # Translate this to the preferred path IP new_src = NetUtils.ip_for_network(src_pref_net, src_host) # And do the same for the destination opposite_switch = self.nib.opposite_switch(switch) dest_host = NetUtils.host_of_ip(dst_ip, self.nib.actual_net_for(opposite_switch)) new_dest = NetUtils.ip_for_network(self.nib.preferred_net(opposite_switch), dest_host) output_actions = [ SetIP4Src(new_src), SetIP4Dst(new_dest), Output(Physical(self.nib.router_port_for_switch(switch))), ] dpid = self.nib.switch_to_dpid(switch) self.main_app.pkt_out(dpid, payload, output_actions)
def send_along_direct_path(self, switch, src_ip, dst_ip, payload): opposite_switch = self.nib.opposite_switch(switch) for ap in self.nib.alternate_paths(): if NetUtils.ip_in_network(dst_ip, ap[opposite_switch]): src_net = ap[switch] src_host = NetUtils.host_of_ip(src_ip, self.nib.actual_net_for(switch)) # Translate this to the direct path IP new_src = NetUtils.ip_for_network(src_net, src_host) output_actions = [SetIP4Src(new_src), Output(Physical(self.nib.router_port_for_switch(switch)))] dpid = self.nib.switch_to_dpid(switch) self.main_app.pkt_out(dpid, payload, output_actions)
def ingress_src_dest_pairs_policy(self): policies = [] for src_dest_pair in self.nib.get_ingress_src_dest_pairs(): (src_ip, dst_ip) = src_dest_pair switch = self.nib.switch_for_ip(src_ip) dpid = self.nib.switch_to_dpid(switch) port = self.nib.port_for_ip(src_ip) src_host = NetUtils.host_of_ip(src_ip, self.nib.actual_net_for(switch)) # If this is going to the preferred network, write a rule choosing the # correct route here. opposite_switch = self.nib.opposite_switch(switch) if NetUtils.ip_in_network(dst_ip, self.nib.actual_net_for(opposite_switch)): # Get host from src_ip src_pref_net = self.nib.preferred_net(switch) new_src = NetUtils.ip_for_network(src_pref_net, src_host) dest_host = NetUtils.host_of_ip(dst_ip, self.nib.actual_net_for(opposite_switch)) new_dest = NetUtils.ip_for_network(self.nib.preferred_net(opposite_switch), dest_host) router_port = self.nib.router_port_for_switch(switch) output_actions = SetIP4Src(new_src) >> SetIP4Dst(new_dest) >> Send(router_port) policies.append( Filter(Policies.at_switch_port(dpid, port) & Policies.is_ip_from_to(src_ip, dst_ip)) >> output_actions ) else: # It's a direct path. Find the path first. for ap in self.nib.alternate_paths(): if NetUtils.ip_in_network(dst_ip, ap[opposite_switch]): alternate_path = ap new_src = NetUtils.ip_for_network(alternate_path[switch], src_host) router_port = self.nib.router_port_for_switch(switch) output_actions = SetIP4Src(new_src) >> Send(router_port) policies.append( Filter(Policies.at_switch_port(dpid, port) & Policies.is_ip_from_to(src_ip, dst_ip)) >> output_actions ) return Union(policies)
def translate_alternate_net(self, dst_ip): # First find out which side (ithaca or nyc) it's on found_side = None for ap in self.alternate_paths(): for side in ["ithaca", "nyc"]: if NetUtils.ip_in_network(dst_ip, ap[side]): found_side = side imaginary_net = ap[side] if side == None: logging.error("Ooops. Got an ARP request for a net we don't know about. Oh well.") return False else: host = NetUtils.host_of_ip(dst_ip, imaginary_net) return NetUtils.ip_for_network(self.actual_net_for(found_side), host)
def learn(self, switch, port_type, port, mac, src_ip): if self.learned(switch, port): return False logging.info("Learning: "+mac+"/"+src_ip+" attached to ( "+switch+", "+str(port)+" )") self.hosts[mac] = (switch, port) self.arp_cache[src_ip] = (switch, port, mac) self.unlearned_ports[switch].remove(port) if port_type == self.ENDHOST_PORT: host_portion = NetUtils.host_of_ip(src_ip, self.coscin_config[switch]["network"]) self.endhosts[switch].append( (host_portion, port, mac, src_ip) ) # We also add entries for this host on all its imaginary paths for ap in self.coscin_config["alternate_paths"]: virtual_ip = NetUtils.ip_for_network(ap[switch], host_portion) self.arp_cache[virtual_ip] = (switch, port, mac) elif port_type == self.ROUTER_PORT: self.router_port[switch] = port else: logging.error("Unknown port type: "+str(port_type)) return False return True
def send_to_host(self, switch, src_ip, dst_ip, payload): # Convert dst_ip to its real form. First find out what the egress switch actually is: for ap in self.nib.alternate_paths(): if NetUtils.ip_in_network(dst_ip, ap[switch]): imaginary_net = ap[switch] real_net = self.nib.actual_net_for(switch) dst_host = NetUtils.host_of_ip(dst_ip, imaginary_net) new_dest_ip = NetUtils.ip_for_network(real_net, dst_host) # If we don't know the port for this address (which might happen if the # IP is on this network, but the host isn't up or doesn't exist) there's not # much we can do with this packet. Send an ARP request and hope the # original packet gets retransmitted (which is normally the case) if not self.nib.learned_ip(new_dest_ip): src_ip = NetUtils.ip_for_network(real_net, 250) self.main_app.send_arp_request(switch, src_ip, new_dest_ip) else: direct_net_port = self.nib.port_for_ip(new_dest_ip) # We also need to translate the alternately-numbered net to a real one. Otherwise the # host (which only knows real networks) may not know what to do with it. new_src_ip = self.nib.translate_alternate_net(src_ip) output_actions = [SetIP4Src(new_src_ip), SetIP4Dst(new_dest_ip), Output(Physical(direct_net_port))] dpid = self.nib.switch_to_dpid(switch) self.main_app.pkt_out(dpid, payload, output_actions)
def translate_ip(self, src_ip, new_net): current_net = self.coscin_net_for(src_ip) if current_net == None: return None src_host = NetUtils.host_of_ip(src_ip, current_net) return NetUtils.ip_for_network(new_net, src_host)