Ejemplo n.º 1
0
void host_addApplication(Host* host, GQuark pluginID,
		SimulationTime startTime, SimulationTime stopTime, gchar* arguments) {
	MAGIC_ASSERT(host);
	Process* application = process_new(pluginID, startTime, stopTime, arguments);
	g_queue_push_tail(host->applications, application);

	StartApplicationEvent* event = startapplication_new(application);
	worker_scheduleEvent((Event*)event, startTime, host->id);

	if(stopTime > startTime) {
		StopApplicationEvent* event = stopapplication_new(application);
		worker_scheduleEvent((Event*)event, stopTime, host->id);
	}
}
Ejemplo n.º 2
0
static void _epoll_check(Epoll* epoll, EpollWatch* watch) {
	MAGIC_ASSERT(epoll);
	MAGIC_ASSERT(watch);

	/* check if we need to schedule a notification */
	gboolean needsNotify = _epollwatch_needsNotify(watch);
	gboolean isScheduled = (epoll->flags & EF_SCHEDULED) ? TRUE : FALSE;

	gpointer watchKey = descriptor_getHandleReference(watch->descriptor);

	if(needsNotify) {
		/* we need to report an event to user */
		g_hash_table_replace(epoll->reports, watchKey, watch);

		if(!isScheduled) {
			/* schedule a notification event for our node */
			NotifyPluginEvent* event = notifyplugin_new(epoll->super.handle);
			SimulationTime delay = 1;
			worker_scheduleEvent((Event*)event, delay, 0);

			epoll->flags |= EF_SCHEDULED;
		}
	} else {
		/* no longer needs reporting */
		g_hash_table_remove(epoll->reports, watchKey);
	}
}
Ejemplo n.º 3
0
void tracker_heartbeat(Tracker* tracker) {
	MAGIC_ASSERT(tracker);

	/* prefer our level over the global config */
	GLogLevelFlags level = tracker->loglevel;
	if(!level) {
		Worker* w = worker_getPrivate();
		if(w->cached_engine) {
			Configuration* c = engine_getConfig(w->cached_engine);
			level = configuration_getHeartbeatLogLevel(c);
		}
	}

	/* prefer our interval over the global config */
	SimulationTime interval = tracker->interval;
	if(!interval) {
		Worker* w = worker_getPrivate();
		if(w->cached_engine) {
			Configuration* c = engine_getConfig(w->cached_engine);
			interval = configuration_getHearbeatInterval(c);
		}
	}

	guint seconds = (guint) (interval / SIMTIME_ONE_SECOND);

	double in = (double) (tracker->inputBytesLastInterval);
	double out = (double)(tracker->outputBytesLastInterval);
	double alloc = (double)(((double)tracker->allocatedBytesLastInterval) / 1024.0);
	double dealloc = (double)(((double)tracker->deallocatedBytesLastInterval) / 1024.0);

	double mem = (double)(((double)tracker->allocatedBytesTotal) / 1024.0);
	double cpuutil = (double)(((double)tracker->processingTimeLastInterval) / interval);

	double avedelayms = 0.0;
	if(tracker->numDelayedLastInterval > 0) {
		double delayms = (double) (((double)tracker->delayTimeLastInterval) / ((double)SIMTIME_ONE_MILLISECOND));
		avedelayms = (double) (delayms / ((double) tracker->numDelayedLastInterval));
	}

	/* log the things we are tracking */
	logging_log(G_LOG_DOMAIN, level, __FUNCTION__,
			"[shadow-heartbeat] CPU %f \%, MEM %f KiB, interval %u seconds, alloc %f KiB, dealloc %f KiB, Rx %f B, Tx %f B, avgdelay %f milliseconds",
			cpuutil, mem, seconds, alloc, dealloc, in, out, avedelayms);

	/* clear interval stats */
	tracker->processingTimeLastInterval = 0;
	tracker->delayTimeLastInterval = 0;
	tracker->numDelayedLastInterval = 0;
	tracker->inputBytesLastInterval = 0;
	tracker->outputBytesLastInterval = 0;
	tracker->allocatedBytesLastInterval = 0;
	tracker->deallocatedBytesLastInterval = 0;

	/* schedule the next heartbeat */
	tracker->lastHeartbeat = worker_getPrivate()->clock_now;
	HeartbeatEvent* heartbeat = heartbeat_new(tracker);
	worker_scheduleEvent((Event*)heartbeat, interval, 0);
}
Ejemplo n.º 4
0
static void _networkinterface_scheduleNextReceive(NetworkInterface* interface) {
	/* the next packets need to be received and processed */
	SimulationTime batchTime = worker_getConfig()->interfaceBatchTime;

	/* receive packets in batches */
	while(!g_queue_is_empty(interface->inBuffer) &&
			interface->receiveNanosecondsConsumed <= batchTime) {
		/* get the next packet */
		Packet* packet = g_queue_pop_head(interface->inBuffer);
		utility_assert(packet);

		/* successfully received */
		packet_addDeliveryStatus(packet, PDS_RCV_INTERFACE_RECEIVED);
		_networkinterface_pcapWritePacket(interface, packet);

		/* free up buffer space */
		guint length = packet_getPayloadLength(packet) + packet_getHeaderSize(packet);
		interface->inBufferLength -= length;

		/* calculate how long it took to 'receive' this packet */
		interface->receiveNanosecondsConsumed += (length * interface->timePerByteDown);

		/* hand it off to the correct socket layer */
		gint key = packet_getDestinationAssociationKey(packet);
		Socket* socket = g_hash_table_lookup(interface->boundSockets, GINT_TO_POINTER(key));

		/* if the socket closed, just drop the packet */
		gint socketHandle = -1;
		if(socket) {
			socketHandle = *descriptor_getHandleReference((Descriptor*)socket);
			socket_pushInPacket(socket, packet);
		} else {
			packet_addDeliveryStatus(packet, PDS_RCV_INTERFACE_DROPPED);
		}

		packet_unref(packet);

		/* count our bandwidth usage by interface, and by socket handle if possible */
		tracker_addInputBytes(host_getTracker(worker_getCurrentHost()),(guint64)length, socketHandle);
	}

	/*
	 * we need to call back and try to receive more, even if we didnt consume all
	 * of our batch time, because we might have more packets to receive then.
	 */
	SimulationTime receiveTime = (SimulationTime) floor(interface->receiveNanosecondsConsumed);
	if(receiveTime >= SIMTIME_ONE_NANOSECOND) {
		/* we are 'receiving' the packets */
		interface->flags |= NIF_RECEIVING;
		/* call back when the packets are 'received' */
		InterfaceReceivedEvent* event = interfacereceived_new(interface);
		/* event destination is our node */
		worker_scheduleEvent((Event*)event, receiveTime, 0);
	}
}
static void _networkinterface_scheduleNextReceive(NetworkInterface* interface) {
	/* the next packets need to be received and processed */
	SimulationTime batchTime = worker_getConfig()->interfaceBatchTime;

	/* receive packets in batches */
	while(!g_queue_is_empty(interface->inBuffer) &&
			interface->receiveNanosecondsConsumed <= batchTime) {
		/* get the next packet */
		Packet* packet = g_queue_pop_head(interface->inBuffer);
		g_assert(packet);

		/* free up buffer space */
		guint length = packet_getPayloadLength(packet) + packet_getHeaderSize(packet);
		interface->inBufferLength -= length;

		/* hand it off to the correct socket layer */
		gint key = packet_getDestinationAssociationKey(packet);
		Socket* socket = g_hash_table_lookup(interface->boundSockets, GINT_TO_POINTER(key));

		gchar* packetString = packet_getString(packet);
		debug("packet in: %s", packetString);
		g_free(packetString);

		_networkinterface_pcapWritePacket(interface, packet);

		/* if the socket closed, just drop the packet */
		gint socketHandle = -1;
		if(socket) {
			socketHandle = *descriptor_getHandleReference((Descriptor*)socket);
			gboolean needsRetransmit = socket_pushInPacket(socket, packet);
			if(needsRetransmit) {
				/* socket can not handle it now, so drop it */
				_networkinterface_dropInboundPacket(interface, packet);
			}
		}

		/* successfully received, calculate how long it took to 'receive' this packet */
		interface->receiveNanosecondsConsumed += (length * interface->timePerByteDown);
		tracker_addInputBytes(node_getTracker(worker_getPrivate()->cached_node),(guint64)length, socketHandle);
	}

	/*
	 * we need to call back and try to receive more, even if we didnt consume all
	 * of our batch time, because we might have more packets to receive then.
	 */
	SimulationTime receiveTime = (SimulationTime) floor(interface->receiveNanosecondsConsumed);
	if(receiveTime >= SIMTIME_ONE_NANOSECOND) {
		/* we are 'receiving' the packets */
		interface->flags |= NIF_RECEIVING;
		/* call back when the packets are 'received' */
		InterfaceReceivedEvent* event = interfacereceived_new(interface);
		/* event destination is our node */
		worker_scheduleEvent((Event*)event, receiveTime, 0);
	}
}
Ejemplo n.º 6
0
void tracker_heartbeat(Tracker* tracker) {
    MAGIC_ASSERT(tracker);

    TrackerFlags flags = _tracker_getFlags(tracker);
    GLogLevelFlags level = _tracker_getLogLevel(tracker);
    SimulationTime interval = _tracker_getLogInterval(tracker);

    /* check to see if node info is being logged */
    if(flags & TRACKER_FLAGS_NODE) {
        _tracker_logNode(tracker, level, interval);
    }

    /* check to see if socket buffer info is being logged */
    if(flags & TRACKER_FLAGS_SOCKET) {
        _tracker_logSocket(tracker, level, interval);
    }

    /* check to see if ram info is being logged */
    if(flags & TRACKER_FLAGS_RAM) {
        _tracker_logRAM(tracker, level, interval);
    }

    /* make sure we have the latest global configured flags */
    tracker->globalFlags = _tracker_parseGlobalFlags();

    /* clear interval stats */
    tracker->processingTimeLastInterval = 0;
    tracker->delayTimeLastInterval = 0;
    tracker->numDelayedLastInterval = 0;
    tracker->allocatedBytesLastInterval = 0;
    tracker->deallocatedBytesLastInterval = 0;

    /* clear the counters */
    memset(&tracker->local, 0, sizeof(IFaceCounters));
    memset(&tracker->remote, 0, sizeof(IFaceCounters));

    SocketStats* ss = NULL;
    GHashTableIter socketIterator;
    g_hash_table_iter_init(&socketIterator, tracker->socketStats);
    while (g_hash_table_iter_next(&socketIterator, NULL, (gpointer*)&ss)) {
        if(ss) {
            memset(&ss->local, 0, sizeof(IFaceCounters));
            memset(&ss->remote, 0, sizeof(IFaceCounters));
        }
    }

    /* schedule the next heartbeat */
    tracker->lastHeartbeat = worker_getCurrentTime();
    HeartbeatEvent* heartbeat = heartbeat_new(tracker);
    worker_scheduleEvent((Event*)heartbeat, interval, 0);
}
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);
	}
}
Ejemplo n.º 8
0
void application_callback(Application* application, CallbackFunc userCallback,
		gpointer userData, gpointer userArgument, guint millisecondsDelay) {
	MAGIC_ASSERT(application);

	/* the application wants a callback. since we need it to happen in our
	 * application and plug-in context, we create a callback to our own
	 * function first, and then redirect and execute theirs
	 */

	ApplicationCallbackData* data = g_new0(ApplicationCallbackData, 1);
	data->callback = userCallback;
	data->data = userData;
	data->argument = userArgument;

	CallbackEvent* event = callback_new((CallbackFunc)_application_callbackTimerExpired, application, data);
	SimulationTime nanos = SIMTIME_ONE_MILLISECOND * millisecondsDelay;

	/* callback to our own node */
	worker_scheduleEvent((Event*)event, nanos, 0);
}
Ejemplo n.º 9
0
void worker_schedulePacket(Packet* packet) {
    /* get our thread-private worker */
    Worker* worker = _worker_getPrivate();
    if(slave_isKilled(worker->slave)) {
        /* the simulation is over, don't bother */
        return;
    }

    in_addr_t srcIP = packet_getSourceIP(packet);
    in_addr_t dstIP = packet_getDestinationIP(packet);

    Address* srcAddress = dns_resolveIPToAddress(worker_getDNS(), (guint32) srcIP);
    Address* dstAddress = dns_resolveIPToAddress(worker_getDNS(), (guint32) dstIP);

    if(!srcAddress || !dstAddress) {
        error("unable to schedule packet because of null addresses");
        return;
    }

    /* check if network reliability forces us to 'drop' the packet */
    gdouble reliability = topology_getReliability(worker_getTopology(), srcAddress, dstAddress);
    Random* random = host_getRandom(worker_getCurrentHost());
    gdouble chance = random_nextDouble(random);

    /* don't drop control packets with length 0, otherwise congestion
     * control has problems responding to packet loss */
    if(chance <= reliability || packet_getPayloadLength(packet) == 0) {
        /* the sender's packet will make it through, find latency */
        gdouble latency = topology_getLatency(worker_getTopology(), srcAddress, dstAddress);
        SimulationTime delay = (SimulationTime) ceil(latency * SIMTIME_ONE_MILLISECOND);

        PacketArrivedEvent* event = packetarrived_new(packet);
        worker_scheduleEvent((Event*)event, delay, (GQuark)address_getID(dstAddress));

        packet_addDeliveryStatus(packet, PDS_INET_SENT);
    } else {
        packet_addDeliveryStatus(packet, PDS_INET_DROPPED);
    }
}
Ejemplo n.º 10
0
static void _tcp_setState(TCP* tcp, enum TCPState state) {
	MAGIC_ASSERT(tcp);

	tcp->stateLast = tcp->state;
	tcp->state = state;

	debug("%s <-> %s: moved from TCP state '%s' to '%s'", tcp->super.boundString, tcp->super.peerString,
			tcp_stateToAscii(tcp->stateLast), tcp_stateToAscii(tcp->state));

	/* some state transitions require us to update the descriptor status */
	switch (state) {
		case TCPS_LISTEN: {
			descriptor_adjustStatus((Descriptor*)tcp, DS_ACTIVE, TRUE);
			break;
		}
		case TCPS_SYNSENT: {
			break;
		}
		case TCPS_SYNRECEIVED: {
			break;
		}
		case TCPS_ESTABLISHED: {
			tcp->flags |= TCPF_WAS_ESTABLISHED;
			if(tcp->state != tcp->stateLast) {
				_tcp_autotune(tcp);
			}
			descriptor_adjustStatus((Descriptor*)tcp, DS_ACTIVE|DS_WRITABLE, TRUE);
			break;
		}
		case TCPS_CLOSING: {
			break;
		}
		case TCPS_CLOSEWAIT: {
			break;
		}
		case TCPS_CLOSED: {
			/* user can no longer use socket */
			descriptor_adjustStatus((Descriptor*)tcp, DS_ACTIVE, FALSE);

			/*
			 * servers have to wait for all children to close.
			 * children need to notify their parents when closing.
			 */
			if(!tcp->server || g_hash_table_size(tcp->server->children) <= 0) {
				if(tcp->child && tcp->child->parent) {
					TCP* parent = tcp->child->parent;

					/* tell my server to stop accepting packets for me
					 * this will destroy the child and NULL out tcp->child */
					g_hash_table_remove(tcp->child->parent->server->children, (gconstpointer)&(tcp->child->key));

					/* if i was the server's last child and its waiting to close, close it */
					g_assert(parent->server);
					if((parent->state == TCPS_CLOSED) && (g_hash_table_size(parent->server->children) <= 0)) {
						/* this will unbind from the network interface and free socket */
						node_closeDescriptor(worker_getPrivate()->cached_node, parent->super.super.super.handle);
					}
				}

				/* this will unbind from the network interface and free socket */
				node_closeDescriptor(worker_getPrivate()->cached_node, tcp->super.super.super.handle);
			}
			break;
		}
		case TCPS_TIMEWAIT: {
			/* schedule a close timer self-event to finish out the closing process */
			TCPCloseTimerExpiredEvent* event = tcpclosetimerexpired_new(tcp);
			worker_scheduleEvent((Event*)event, CONFIG_TCPCLOSETIMER_DELAY, 0);
			break;
		}
		default:
			break;
	}
}
Ejemplo n.º 11
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);
	}
}