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 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 policy(self): # One rule sends all traffic from unlearned ports to controller. is_at_unlearned_port = [] unlearned_ports = self.nib.get_unlearned_ports() for switch, ports in unlearned_ports.iteritems(): dpid = self.nib.switch_to_dpid(switch) for port in ports: is_at_unlearned_port.append(Policies.at_switch_port(dpid,port)) policies = [ Filter(Or(is_at_unlearned_port)) >> Policies.send_to_controller() ] # Output rules for each pair of learned endhosts so intranet traffic can be handled nicely on # the switch. # TODO: If the app is restarted but hosts are hanging onto ARP cache entries, they won't be able # to get packets to each other. This is hard to handle because a "Port = n AND Dest Net = this" # might have overlap with other rules ... I think # Therefore, I'm letting this go for now because (1) intranet host # traffic is relatively rare (2) ARP cache entries usually timeout in 10 minutes anyway. # L2Switch.policy. for switch in self.nib.switches_present(): dpid = self.nib.switch_to_dpid(switch) # The router interface is no different than a regular host with regard to intranet traffic. all_hosts = copy.deepcopy(self.nib.get_endhosts(switch)) all_hosts.append( (None, self.nib.router_port_for_switch(switch) , None, self.nib.router_ip_for_switch(switch) ) ) for src_endhost in all_hosts: (_, src_port, _, src_ip) = src_endhost for dst_endhost in all_hosts: (_, dst_port, _, dst_ip) = dst_endhost # No rule for a host to itself, obviously if src_ip != dst_ip: policies.append( Filter(Policies.is_ip_from_to(src_ip, dst_ip) & Policies.at_switch_port(dpid, src_port) ) >> Send(dst_port) ) policies.append( Filter(Policies.is_arp_from_to(src_ip, dst_ip) & Policies.at_switch_port(dpid, src_port) ) >> Send(dst_port) ) return Union(policies)