def _init_switches(self): self.dpids = getStats.get_dpids() for dpid in self.dpids: vid = Vid(sw=dpid, host=0x00) switch = Switch(dpid=dpid, vid=vid) if dpid == self.DPID: self.switch = switch self.topo.addSwitch(switch) # table 0 # handle arp request if Switch.is_edge_switch(dpid): postFlows.add_arp_request_flow(dpid, Vid.vid2mac(0x20, 0x00)) postFlows.add_arp_dir_transfer_flow(dpid, Vid.vid2mac(0x20, 0x00)) # disable lldp postFlows.add_lldp_disable_flow(dpid) # rule for packet from hosts postFlows.add_host_packet_modify_flow(dpid) # set go to table 2 postFlows.add_resubmit_flow(dpid, table_id=0, goto_id=2)
def _handle_host_register(self, datapath, in_port, src_mac, src_ip, dst_ip): # proxy is registering # src_mac should be the hwaddr of host host = self.server.get_host(src_mac) if host: # host is registering its first vid self.logger.info('Vid register request received from %s', host.local_mac) self.server.register_host(host) self.server.add_host_receiving_entry(host) src_mac = host.fake_mac dst_mac = Vid.vid2mac(host.switch.vid.sw, host.vid.host) self._send_arp_reply(datapath, in_port, src_mac, dst_mac, src_ip, dst_ip) self.logger.info('Answer host register with vid %s', src_mac)
def answer_host_vid_update_request(self, host): affected_dpids = [] new_host_vid = Vid.get_next_host_vid() self.del_host_receiving_flow(host.dpid, host.vid, host.port) self.del_host_forwarding_flow(host.dpid, host.vid, host.switch.vid) for switch in self.topo.switches.itervalues(): affected = False for h in switch.host_forwarding_table: if h.vid == host.vid: affected = True affected_dpids.append(switch.dpid) h.vid = new_host_vid if affected: self.del_host_forwarding_flow(switch.dpid, host.vid, host.switch.vid) self.add_host_forwarding_flow(switch.dpid, new_host_vid, host.switch.vid) host.update_vid(new_host_vid) host.set_fake_mac(Vid.vid2mac(host.vid.sw, host.vid.host)) self.add_host_receiving_entry(host) return affected_dpids
def exec_vid_update(self): self.del_arp_dir_transfer_flows() self.topo.updateRoutingPrefixes() # clear table 1, 2 self._clear_routing_tables() # push table 2 self._push_routing_tables() # push table 1 self._push_host_forwarding_tables() # update server vid # change table 3 of server edge switch, matching server's new vid self.del_host_receiving_flow(self.DPID, self.vid, self.PORT) self.vid = Vid.get_next_host_vid() self._enable_network_access() self.add_arp_dir_transfer_flows() self.mod_arp_request_flows()
def _handle_arp(self, datapath, in_port, src_mac, src_ip, dst_ip): self.logger.info("Handling ARP...") # arp askee dst_host = self.server.find_host_by_ip(dst_ip) self.logger.info("ARP askee is: %s", str(dst_host)) # arp asker src_host = self.server.find_host_by_fake_mac(src_mac) self.logger.info("ARP asker is: %s", str(src_host)) if dst_host and src_host: if self.server.add_host_forwarding_entry(src_host.switch.dpid, dst_host): self.logger.info("Adding new host forwarding entry to %s, host.fake_mac == %s", src_host.dpid, dst_host.fake_mac) dst_mac = dst_host.fake_mac src_mac = Vid.vid2mac(src_host.switch.vid.sw, src_host.vid.host) self.logger.info('PacketIn: ARP, %s is asking for %s', src_ip, dst_ip) self._send_arp_reply(datapath, in_port, dst_mac, src_mac, dst_ip, src_ip) self.logger.info('Answer ARP for %s with MAC address %s', dst_ip, dst_mac)
class MTDServer(object): DPID = 32 PORT = 1 vid = Vid(0x00, 0x00) """Ultravag server app""" def __init__(self): # init topology and set ip links self.topo = Topology(links=getStats.get_topo_links()) # init switches and set up flows in table 0 self._init_switches() # build routing tables self._build_routing_tables() # write MTD edge switch flow self._enable_network_access() def _init_switches(self): self.dpids = getStats.get_dpids() for dpid in self.dpids: vid = Vid(sw=dpid, host=0x00) switch = Switch(dpid=dpid, vid=vid) if dpid == self.DPID: self.switch = switch self.topo.addSwitch(switch) # table 0 # handle arp request if Switch.is_edge_switch(dpid): postFlows.add_arp_request_flow(dpid, Vid.vid2mac(0x20, 0x00)) postFlows.add_arp_dir_transfer_flow(dpid, Vid.vid2mac(0x20, 0x00)) # disable lldp postFlows.add_lldp_disable_flow(dpid) # rule for packet from hosts postFlows.add_host_packet_modify_flow(dpid) # set go to table 2 postFlows.add_resubmit_flow(dpid, table_id=0, goto_id=2) def _enable_network_access(self): postFlows.add_host_receiving_flow(self.DPID, self.vid, self.PORT) def get_host(self, mac_addr): host = self.find_host_by_fake_mac(mac_addr) if host: return host return getStats.get_host(mac_addr) def register_host(self, host): host.update_vid(Vid.get_next_host_vid()) host.set_fake_mac(Vid.vid2mac(host.vid.sw, host.vid.host)) self.topo.switches[host.dpid].addHost(host) def add_host_receiving_entry(self, host): # table 3 postFlows.add_host_receiving_flow(host.dpid, host.vid, host.port) def add_host_forwarding_entry(self, dpid, host): # table 1 if self.topo.switches[dpid].add_host_forwarding_entry(host): postFlows.add_host_forwarding_flow(dpid, host.vid, host.switch.vid) return True return False def _build_routing_tables(self): self.topo.constructRT() self._push_routing_tables() def _push_routing_tables(self): for switch in self.topo.switches.itervalues(): # table 2: routing table # set go to table 3 (host receiving table) postFlows.add_goto_table3_flow(switch.dpid, switch.vid) for level, entry in switch.rt.rtbl.iteritems(): if level != 0 and entry['nexthop']: postFlows.add_routing_table_flow(switch.dpid, entry['prefix'], entry['nexthop'][0]) def _push_host_forwarding_tables(self): for switch in self.topo.switches.itervalues(): # table 1: host forwarding table self._push_host_forwarding_table(switch) def _push_host_forwarding_table(self, switch): for host in switch.host_forwarding_table: self.add_host_forwarding_flow(switch.dpid, host.vid, host.switch.vid) def find_host_by_ip(self, ip): return self.topo.find_host_by_ip(ip) def find_host_by_fake_mac(self, fake_mac): return self.topo.find_host_by_fake_mac(fake_mac) def _clear_routing_tables(self): for dpid in self.dpids: postFlows.clear_routing_table(dpid, table_id=1) postFlows.clear_routing_table(dpid, table_id=2) def mod_arp_request_flows(self): for dpid in self.dpids: if Switch.is_edge_switch(dpid): self.mod_arp_request_flow(dpid) def del_arp_dir_transfer_flows(self): for dpid in self.dpids: if Switch.is_edge_switch(dpid): self.del_arp_dir_transfer_flow(dpid) def add_arp_dir_transfer_flows(self): for dpid in self.dpids: if Switch.is_edge_switch(dpid): self.add_arp_dir_transfer_flow(dpid) def mod_arp_request_flow(self, dpid): postFlows.mod_arp_request_flow( dpid, Vid.vid2mac(self.switch.vid.sw, self.vid.host)) def del_arp_dir_transfer_flow(self, dpid): postFlows.del_arp_dir_transfer_flow( dpid, Vid.vid2mac(self.switch.vid.sw, self.vid.host)) def add_arp_dir_transfer_flow(self, dpid): postFlows.add_arp_dir_transfer_flow( dpid, Vid.vid2mac(self.switch.vid.sw, self.vid.host)) def del_host_receiving_flow(self, dpid, vid, port): postFlows.del_host_receiving_flow(dpid, vid, port) def add_host_forwarding_flow(self, dpid, host_vid, switch_vid): postFlows.add_host_forwarding_flow(dpid, host_vid, switch_vid) def del_host_forwarding_flow(self, dpid, host_vid, switch_vid): postFlows.del_host_forwarding_flow(dpid, host_vid, switch_vid) def exec_vid_update(self): self.del_arp_dir_transfer_flows() self.topo.updateRoutingPrefixes() # clear table 1, 2 self._clear_routing_tables() # push table 2 self._push_routing_tables() # push table 1 self._push_host_forwarding_tables() # update server vid # change table 3 of server edge switch, matching server's new vid self.del_host_receiving_flow(self.DPID, self.vid, self.PORT) self.vid = Vid.get_next_host_vid() self._enable_network_access() self.add_arp_dir_transfer_flows() self.mod_arp_request_flows() def answer_host_vid_update_request(self, host): affected_dpids = [] new_host_vid = Vid.get_next_host_vid() self.del_host_receiving_flow(host.dpid, host.vid, host.port) self.del_host_forwarding_flow(host.dpid, host.vid, host.switch.vid) for switch in self.topo.switches.itervalues(): affected = False for h in switch.host_forwarding_table: if h.vid == host.vid: affected = True affected_dpids.append(switch.dpid) h.vid = new_host_vid if affected: self.del_host_forwarding_flow(switch.dpid, host.vid, host.switch.vid) self.add_host_forwarding_flow(switch.dpid, new_host_vid, host.switch.vid) host.update_vid(new_host_vid) host.set_fake_mac(Vid.vid2mac(host.vid.sw, host.vid.host)) self.add_host_receiving_entry(host) return affected_dpids def add_host_sock(self, sock, ip_addr): host = self.topo.find_host_by_ip(ip_addr) if host: host.set_sock(sock) def set_local_arp_table(self, ip_addr, new_mac_addr): os.system("sudo arp -s %s %s" % (ip_addr, new_mac_addr))
def register_host(self, host): host.update_vid(Vid.get_next_host_vid()) host.set_fake_mac(Vid.vid2mac(host.vid.sw, host.vid.host)) self.topo.switches[host.dpid].addHost(host)
def add_arp_dir_transfer_flow(self, dpid): postFlows.add_arp_dir_transfer_flow( dpid, Vid.vid2mac(self.switch.vid.sw, self.vid.host))
def mod_arp_request_flow(self, dpid): postFlows.mod_arp_request_flow( dpid, Vid.vid2mac(self.switch.vid.sw, self.vid.host))