static void _networkinterface_dropInboundPacket(NetworkInterface* interface, Packet* packet) {
	MAGIC_ASSERT(interface);

	/* drop incoming packet that traversed the network link from source */

	if(networkinterface_getIPAddress(interface) == packet_getSourceIP(packet)) {
		/* packet is on our own interface, so event destination is our node */
		PacketDroppedEvent* event = packetdropped_new(packet);
		worker_scheduleEvent((Event*)event, 1, 0);
	} else {
		/* let the network schedule the event with appropriate delays */
		network_scheduleRetransmit(interface->network, packet);
	}
}
示例#2
0
static void _networkinterface_scheduleNextSend(NetworkInterface* interface) {
	/* the next packet needs to be sent according to bandwidth limitations.
	 * we need to spend time sending it before sending the next. */
	SimulationTime batchTime = worker_getConfig()->interfaceBatchTime;

	/* loop until we find a socket that has something to send */
	while(interface->sendNanosecondsConsumed <= batchTime) {
		gint socketHandle = -1;

		/* choose which packet to send next based on our queuing discipline */
		Packet* packet;
		switch(interface->qdisc) {
			case NIQ_RR: {
				packet = _networkinterface_selectRoundRobin(interface, &socketHandle);
				break;
			}
			case NIQ_FIFO:
			default: {
				packet = _networkinterface_selectFirstInFirstOut(interface, &socketHandle);
				break;
			}
		}
		if(!packet) {
			break;
		}

		packet_addDeliveryStatus(packet, PDS_SND_INTERFACE_SENT);

		/* now actually send the packet somewhere */
		if(networkinterface_getIPAddress(interface) == packet_getDestinationIP(packet)) {
			/* packet will arrive on our own interface */
			PacketArrivedEvent* event = packetarrived_new(packet);
			/* event destination is our node */
			worker_scheduleEvent((Event*)event, 1, 0);
		} else {
			/* let the worker schedule with appropriate delays */
			worker_schedulePacket(packet);
		}

		/* successfully sent, calculate how long it took to 'send' this packet */
		guint length = packet_getPayloadLength(packet) + packet_getHeaderSize(packet);

		interface->sendNanosecondsConsumed += (length * interface->timePerByteUp);
		tracker_addOutputBytes(host_getTracker(worker_getCurrentHost()),(guint64)length, socketHandle);
		_networkinterface_pcapWritePacket(interface, packet);

		/* sending side is done with its ref */
		packet_unref(packet);
	}

	/*
	 * we need to call back and try to send more, even if we didnt consume all
	 * of our batch time, because we might have more packets to send then.
	 */
	SimulationTime sendTime = (SimulationTime) floor(interface->sendNanosecondsConsumed);
	if(sendTime >= SIMTIME_ONE_NANOSECOND) {
		/* we are 'sending' the packets */
		interface->flags |= NIF_SENDING;
		/* call back when the packets are 'sent' */
		InterfaceSentEvent* event = interfacesent_new(interface);
		/* event destination is our node */
		worker_scheduleEvent((Event*)event, sendTime, 0);
	}
}
示例#3
0
Host* host_new(GQuark id, gchar* hostname, gchar* ipHint, gchar* geocodeHint, gchar* typeHint,
		guint64 requestedBWDownKiBps, guint64 requestedBWUpKiBps,
		guint cpuFrequency, gint cpuThreshold, gint cpuPrecision, guint nodeSeed,
		SimulationTime heartbeatInterval, GLogLevelFlags heartbeatLogLevel, gchar* heartbeatLogInfo,
		GLogLevelFlags logLevel, gboolean logPcap, gchar* pcapDir, gchar* qdisc,
		guint64 receiveBufferSize, gboolean autotuneReceiveBuffer,
		guint64 sendBufferSize, gboolean autotuneSendBuffer,
		guint64 interfaceReceiveLength) {
	Host* host = g_new0(Host, 1);
	MAGIC_INIT(host);

	host->id = id;
	host->name = g_strdup(hostname);
	host->random = random_new(nodeSeed);

	/* get unique virtual address identifiers for each network interface */
	Address* loopbackAddress = dns_register(worker_getDNS(), host->id, host->name, "127.0.0.1");
	Address* ethernetAddress = dns_register(worker_getDNS(), host->id, host->name, ipHint);

	/* connect to topology and get the default bandwidth */
	guint64 bwDownKiBps = 0, bwUpKiBps = 0;
	topology_attach(worker_getTopology(), ethernetAddress, host->random,
			ipHint, geocodeHint, typeHint, &bwDownKiBps, &bwUpKiBps);

	/* prefer assigned bandwidth if available */
	if(requestedBWDownKiBps) {
		bwDownKiBps = requestedBWDownKiBps;
	}
	if(requestedBWUpKiBps) {
		bwUpKiBps = requestedBWUpKiBps;
	}

	/* virtual addresses and interfaces for managing network I/O */
	NetworkInterface* loopback = networkinterface_new(loopbackAddress, G_MAXUINT32, G_MAXUINT32,
			logPcap, pcapDir, qdisc, interfaceReceiveLength);
	NetworkInterface* ethernet = networkinterface_new(ethernetAddress, bwDownKiBps, bwUpKiBps,
			logPcap, pcapDir, qdisc, interfaceReceiveLength);

	host->interfaces = g_hash_table_new_full(g_direct_hash, g_direct_equal,
			NULL, (GDestroyNotify) networkinterface_free);
	g_hash_table_replace(host->interfaces, GUINT_TO_POINTER((guint)networkinterface_getIPAddress(ethernet)), ethernet);
	g_hash_table_replace(host->interfaces, GUINT_TO_POINTER((guint)htonl(INADDR_LOOPBACK)), loopback);

	host->defaultInterface = ethernet;

	/* thread-level event communication with other nodes */
	g_mutex_init(&(host->lock));
	host->events = eventqueue_new();

	host->availableDescriptors = g_queue_new();
	host->descriptorHandleCounter = MIN_DESCRIPTOR;

	/* virtual descriptor management */
	host->descriptors = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, descriptor_unref);
	host->receiveBufferSize = receiveBufferSize;
	host->sendBufferSize = sendBufferSize;
	host->autotuneReceiveBuffer = autotuneReceiveBuffer;
	host->autotuneSendBuffer = autotuneSendBuffer;

	host->shadowToOSHandleMap = g_hash_table_new(g_direct_hash, g_direct_equal);
    host->osToShadowHandleMap = g_hash_table_new(g_direct_hash, g_direct_equal);
    host->unixPathToPortMap = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);

	/* applications this node will run */
	host->applications = g_queue_new();

	host->cpu = cpu_new(cpuFrequency, cpuThreshold, cpuPrecision);
	host->tracker = tracker_new(heartbeatInterval, heartbeatLogLevel, heartbeatLogInfo);
	host->logLevel = logLevel;
	host->logPcap = logPcap;
	host->pcapDir = pcapDir;

	message("Created Host '%s', ip %s, "

			"%"G_GUINT64_FORMAT" bwUpKiBps, %"G_GUINT64_FORMAT" bwDownKiBps, %"G_GUINT64_FORMAT" initSockSendBufSize, %"G_GUINT64_FORMAT" initSockRecvBufSize, "
			"%u cpuFrequency, %i cpuThreshold, %i cpuPrecision, %u seed",
			g_quark_to_string(host->id), networkinterface_getIPName(host->defaultInterface),
			bwUpKiBps, bwDownKiBps, sendBufferSize, receiveBufferSize,
			cpuFrequency, cpuThreshold, cpuPrecision, nodeSeed);

	return host;
}
示例#4
0
gint host_connectToPeer(Host* host, gint handle, const struct sockaddr* address) {
	MAGIC_ASSERT(host);

	sa_family_t family = 0;
	in_addr_t peerIP = 0;
	in_port_t peerPort = 0;

    if(address->sa_family == AF_INET) {
        struct sockaddr_in* saddr = (struct sockaddr_in*) address;

        family = saddr->sin_family;
        peerIP = saddr->sin_addr.s_addr;
        peerPort = saddr->sin_port;

    } else if (address->sa_family == AF_UNIX) {
        struct sockaddr_un* saddr = (struct sockaddr_un*) address;

        family = saddr->sun_family;
        gchar* sockpath = saddr->sun_path;

        peerIP = htonl(INADDR_LOOPBACK);
        gpointer val = g_hash_table_lookup(host->unixPathToPortMap, sockpath);
        if(val) {
            peerPort = (in_port_t)GPOINTER_TO_UINT(val);
        }
    }

	in_addr_t loIP = htonl(INADDR_LOOPBACK);

	/* make sure we will be able to route this later */
	if(peerIP != loIP) {
		Address* myAddress = networkinterface_getAddress(host->defaultInterface);
		Address* peerAddress = dns_resolveIPToAddress(worker_getDNS(), peerIP);
		if(!peerAddress || !topology_isRoutable(worker_getTopology(), myAddress, peerAddress)) {
			/* can't route it - there is no node with this address */
			gchar* peerAddressString = address_ipToNewString(peerIP);
			warning("attempting to connect to address '%s:%u' for which no host exists", peerAddressString, ntohs(peerPort));
			g_free(peerAddressString);
			return ECONNREFUSED;
		}
	}

	Descriptor* descriptor = host_lookupDescriptor(host, handle);
	if(descriptor == NULL) {
		warning("descriptor handle '%i' not found", handle);
		return EBADF;
	}

	DescriptorStatus status = descriptor_getStatus(descriptor);
	if(status & DS_CLOSED) {
		warning("descriptor handle '%i' not a valid open descriptor", handle);
		return EBADF;
	}

	DescriptorType type = descriptor_getType(descriptor);
	if(type != DT_TCPSOCKET && type != DT_UDPSOCKET) {
		warning("wrong type for descriptor handle '%i'", handle);
		return ENOTSOCK;
	}

	Socket* socket = (Socket*) descriptor;

	if(!socket_isFamilySupported(socket, family)) {
		return EAFNOSUPPORT;
	}

	if(type == DT_TCPSOCKET) {
		gint error = tcp_getConnectError((TCP*)socket);
		if(error) {
			return error;
		}
	}

	if (address->sa_family == AF_UNIX) {
        struct sockaddr_un* saddr = (struct sockaddr_un*) address;
        socket_setUnixPath(socket, saddr->sun_path, FALSE);
    }

	if(!socket_isBound(socket)) {
		/* do an implicit bind to a random port.
		 * use default interface unless the remote peer is on loopback */
		in_addr_t defaultIP = networkinterface_getIPAddress(host->defaultInterface);

		in_addr_t bindAddress = loIP == peerIP ? loIP : defaultIP;
		in_port_t bindPort = _host_getRandomFreePort(host, bindAddress, type);
        if(!bindPort) {
            return EADDRNOTAVAIL;
        }

		_host_associateInterface(host, socket, bindAddress, bindPort);
	}

	return socket_connectToPeer(socket, peerIP, peerPort, family);
}
示例#5
0
// TODO replace this with address object functions
in_addr_t host_getDefaultIP(Host* host) {
	MAGIC_ASSERT(host);
	return networkinterface_getIPAddress(host->defaultInterface);
}