def callback(frame): ''' The action after receiving datagram from link layer. First unpack datagram Case1: if the outside datagram is received by destination end router, it will first do NAT and update datgram, then push upward Case2; if the internal datagram is received by destination, no need for NAT, directly push upward Case3: if this datagram is received in core routers, find the next forwarding hop ip and convert into mac, then send it by linklayer :param frame: received datagram from linklayer :return: None ''' network, transport, action = unpack(frame) if action == ACTION_PUSH: if network.dst_ip == util.get_local_ipv4_address(): IP.push(frame) elif network.dst_ip in forwarding_table: forwarding_ip = forwarding_table[network.dst_ip] if forwarding_ip != WAN_ip: dst_ip = forwarding_ip else: dst_ip = network.dst_ip if dst_ip != forwarding_ip: print('forwaring to', forwarding_table[network.dst_ip]) dst_mac = util.ip2mac(dst_ip) linklayer.sendto(dst_mac, frame) elif (network.dst_ip, transport.dst_port) in NAT_in : network.dst_ip, transport.dst_port = NAT_in[(network.dst_ip, transport.dst_port)] frame = pack(network, transport) IP.push(frame) else: ICMP.host_unreachable(WAN_ip, network.src_ip)
def dijsktra(): ''' This function is to to generate a min cost path for a given start node and update the forwarding table :param startNode means the given start node :return: None ''' global forwarding_table start_ip = util.get_local_ipv4_address() # Initialize visited list notVisited = set() for i in NETWORK: notVisited.add(i) # Initalize min_cost list min_cost = {} pre_node = None # the value of min_cost is a editable list, the first element is min_cost, the second is previous node for i in NETWORK: if not i == start_ip: min_cost[i] = [float('inf'),pre_node] else: min_cost[i] = [0,pre_node] # do dijsktra while notVisited: current_node = get_current_node(min_cost, notVisited) notVisited.remove(current_node) neighbor_set = NETWORK[current_node] for key in neighbor_set: if key[0] in notVisited: if min_cost[current_node][0] + key[1] < min_cost[key[0]][0]: min_cost[key[0]][0] = min_cost[current_node][0] +key[1] min_cost[key[0]][1] = current_node for key in min_cost: value = min_cost[key] path = [] if value[0] == 0: path.append(key) # find path by back propagation while value[1] != None: path.append(value[1]) value = min_cost[value[1]] path.reverse() path.append(key) if len(path)>1: forwarding_table[key] = path[1] elif len(path)==1: forwarding_table[key] = path[0] else: forwarding_table[key] = key print('pass')
from mysocket import * from LinkLayer import util ip = util.get_local_ipv4_address() port = 5000 local_address = (ip, port) remote_address = ('10.21.108.47', 5000) ClientSocket = socket(AF_INET, SOCK_STREAM) ClientSocket.bind(local_address) ClientSocket.connect(remote_address) for i in range(10): ClientSocket.send("{}".format(i).encode()) raw_message = ClientSocket.recv(2048) print("\n---------------\n", raw_message.decode(), "\n----------------\n")
def get_local_ip(): return util.get_local_ipv4_address()