예제 #1
0
 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)
예제 #2
0
  def policy(self):
    policies = []
    for switch in self.nib.switches_present():
      dpid = self.nib.switch_to_dpid(switch)
      # In normal mode, we capture ARP requests for IP's that don't really exist.  You can
      # think of them as symbolic links to the real IP.  We capture .1 address of
      # each of the endpoint networks, plus any real hosts on the net

      # And we capture ARP requests for the alternate paths.  These will always be for 
      # hosts that have no real estate on the imaginary link, as in 192.168.156.100 along 
      # the 192.168.156.* imaginary network.  This will be translated to the real net 192.168.56.100
      # Note: only the routers actually send these requests, not end hosts, who always send them
      # to a default gateway.  
      for ap in self.nib.alternate_paths():
        (net, mask) = NetUtils.net_mask(ap[switch])
        policies.append(Filter(Policies.at_switch(dpid) & Policies.is_arp() & IP4DstEq(net,mask)) >> Policies.send_to_controller())

    return Union(policies)
예제 #3
0
    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)
예제 #4
0
    def capture_new_source_dest_pairs_policy(self):
        policies = []
        for switch in self.nib.switches_present():
            dpid = self.nib.switch_to_dpid(switch)
            for endhost in self.nib.get_endhosts(switch):
                (host, host_port, host_mac, host_ip) = endhost
                opposite_switch = self.nib.opposite_switch(switch)
                dest_cdr = self.nib.actual_net_for(opposite_switch)
                (dest_net, dest_mask) = NetUtils.net_mask(dest_cdr)

                # Note we really don't have to test for source IP, but it's extra security
                policies.append(
                    Filter(
                        Policies.at_switch_port(dpid, host_port)
                        & Policies.is_ip()
                        & IP4SrcEq(host_ip)
                        & IP4DstEq(dest_net, dest_mask)
                        & self.destination_not_known_host_on_net(host_ip, dest_cdr)
                    )
                    >> Policies.send_to_controller()
                )
                for ap in self.nib.alternate_paths():
                    dest_cdr = ap[opposite_switch]
                    (dest_net, dest_mask) = NetUtils.net_mask(dest_cdr)
                    policies.append(
                        Filter(
                            Policies.at_switch_port(dpid, host_port)
                            & Policies.is_ip()
                            & IP4SrcEq(host_ip)
                            & IP4DstEq(dest_net, dest_mask)
                            & self.destination_not_known_host_on_net(host_ip, dest_cdr)
                        )
                        >> Policies.send_to_controller()
                    )

            # Now handle incoming packets for all our home networks.  We need to learn
            # those (src, dest) pairs as well
            for ap in self.nib.alternate_paths():
                dest_cdr = ap[switch]
                (dest_net, dest_mask) = NetUtils.net_mask(dest_cdr)
                policies.append(
                    Filter(Policies.is_ip() & IP4DstEq(dest_net, dest_mask) & self.src_dest_pair_not_learned(dest_cdr))
                    >> Policies.send_to_controller()
                )

        return Union(policies)
예제 #5
0
  def policy(self):
    policies = []
    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.
      learned_host_ports = [ p for (_, p, _, _) in self.nib.get_endhosts(switch)]
      learned_host_ports.append( self.nib.router_port_for_switch(switch) )

      for src_endhost_port in learned_host_ports:
        output_actions = [ Send(p) for p in self.nib.ports_on_switch(switch) if p != src_endhost_port ]
        policies.append( 
          Filter (Policies.at_switch_port(dpid, src_endhost_port) & EthDstEq("ff:ff:ff:ff:ff:ff")) >> 
          Seq(output_actions)
        )

    return Union(policies)
예제 #6
0
  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)
예제 #7
0
 def router_learning_policy(self):
   # In the intial config, grab all ARP replies for ourselves
   return Filter( Policies.is_arp() ) >> Policies.send_to_controller()