void tracker_addOutputBytes(Tracker* tracker, Packet* packet, gint handle) { MAGIC_ASSERT(tracker); TrackerFlags flags = _tracker_getFlags(tracker); if(!(flags & TRACKER_FLAGS_NODE) && !(flags & TRACKER_FLAGS_SOCKET)) { return; } gboolean isLocal = packet_getSourceIP(packet) == htonl(INADDR_LOOPBACK); gsize header = (gsize)packet_getHeaderSize(packet); gsize payload = (gsize)packet_getPayloadLength(packet); PacketDeliveryStatusFlags status = packet_getDeliveryStatus(packet); if(flags & TRACKER_FLAGS_NODE) { if(isLocal) { _tracker_updateCounters(&tracker->local.outCounters, header, payload, status); } else { _tracker_updateCounters(&tracker->remote.outCounters, header, payload, status); } } if(flags & TRACKER_FLAGS_SOCKET) { SocketStats* ss = g_hash_table_lookup(tracker->socketStats, &handle); if(ss) { if(isLocal) { _tracker_updateCounters(&ss->local.outCounters, header, payload, status); } else { _tracker_updateCounters(&ss->remote.outCounters, header, payload, status); } } } }
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); } }
void networkinterface_packetArrived(NetworkInterface* interface, Packet* packet) { MAGIC_ASSERT(interface); /* a packet arrived. lets try to receive or buffer it */ guint length = packet_getPayloadLength(packet) + packet_getHeaderSize(packet); gssize space = interface->inBufferSize - interface->inBufferLength; g_assert(space >= 0); if(length <= space) { /* we have space to buffer it */ g_queue_push_tail(interface->inBuffer, packet); interface->inBufferLength += length; /* we need a trigger if we are not currently receiving */ if(!(interface->flags & NIF_RECEIVING)) { _networkinterface_scheduleNextReceive(interface); } } else { /* buffers are full, drop packet */ _networkinterface_dropInboundPacket(interface, packet); } }
void networkinterface_packetArrived(NetworkInterface* interface, Packet* packet) { MAGIC_ASSERT(interface); /* a packet arrived. lets try to receive or buffer it */ guint length = packet_getPayloadLength(packet) + packet_getHeaderSize(packet); gssize space = interface->inBufferSize - interface->inBufferLength; utility_assert(space >= 0); if(length <= space) { /* we have space to buffer it */ packet_ref(packet); g_queue_push_tail(interface->inBuffer, packet); interface->inBufferLength += length; packet_addDeliveryStatus(packet, PDS_RCV_INTERFACE_BUFFERED); /* we need a trigger if we are not currently receiving */ if(!(interface->flags & NIF_RECEIVING)) { _networkinterface_scheduleNextReceive(interface); } } else { /* buffers are full, drop packet */ packet_addDeliveryStatus(packet, PDS_RCV_INTERFACE_DROPPED); } }
void pcapwriter_writePacket(PCapWriter* pcap, Packet* packet) { if(!pcap || !pcap->pcapFile || !packet) { return; } guint32 ts_sec; /* timestamp seconds */ guint32 ts_usec; /* timestamp microseconds */ guint32 incl_len; /* number of octets of packet saved in file */ guint32 orig_len; /* actual length of packet */ /* get the current time that the packet is being sent/received */ SimulationTime now = worker_getCurrentTime(); ts_sec = now / SIMTIME_ONE_SECOND; ts_usec = (now % SIMTIME_ONE_SECOND) / SIMTIME_ONE_MICROSECOND; /* get the header and payload lengths */ guint headerSize = packet_getHeaderSize(packet); guint payloadLength = packet_getPayloadLength(packet); incl_len = headerSize + payloadLength; orig_len = headerSize + payloadLength; /* get the TCP header and the payload */ PacketTCPHeader tcpHeader; guchar *payload = g_new0(guchar, payloadLength); packet_getTCPHeader(packet, &tcpHeader); packet_copyPayload(packet, 0, payload, payloadLength); /* write the PCAP packet header to the pcap file */ fwrite(&ts_sec, sizeof(ts_sec), 1, pcap->pcapFile); fwrite(&ts_usec, sizeof(ts_usec), 1, pcap->pcapFile); fwrite(&incl_len, sizeof(incl_len), 1, pcap->pcapFile); fwrite(&orig_len, sizeof(orig_len), 1, pcap->pcapFile); /* write the ethernet header */ guint8 destinationMAC[6] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB}; guint8 sourceMAC[6] = {0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6}; guint16 type = htons(0x0800); fwrite(destinationMAC, 1, sizeof(destinationMAC), pcap->pcapFile); fwrite(sourceMAC, 1, sizeof(sourceMAC), pcap->pcapFile); fwrite(&type, 1, sizeof(type), pcap->pcapFile); /* write the IP header */ guint8 versionAndHeaderLength = 0x45; guint8 fields = 0x00; guint16 totalLength = htons(orig_len - 14); guint16 identification = 0x0000; guint16 flagsAndFragment = 0x0040; guint8 timeToLive = 64; guint8 protocol = 6; /* TCP */ guint16 headerChecksum = 0x0000; guint32 sourceIP = tcpHeader.sourceIP; guint32 destinationIP = tcpHeader.destinationIP; fwrite(&versionAndHeaderLength, 1, sizeof(versionAndHeaderLength), pcap->pcapFile); fwrite(&fields, 1, sizeof(fields), pcap->pcapFile); fwrite(&totalLength, 1, sizeof(totalLength), pcap->pcapFile); fwrite(&identification, 1, sizeof(identification), pcap->pcapFile); fwrite(&flagsAndFragment, 1, sizeof(flagsAndFragment), pcap->pcapFile); fwrite(&timeToLive, 1, sizeof(timeToLive), pcap->pcapFile); fwrite(&protocol, 1, sizeof(protocol), pcap->pcapFile); fwrite(&headerChecksum, 1, sizeof(headerChecksum), pcap->pcapFile); fwrite(&sourceIP, 1, sizeof(sourceIP), pcap->pcapFile); fwrite(&destinationIP, 1, sizeof(destinationIP), pcap->pcapFile); /* write the TCP header */ guint16 sourcePort = tcpHeader.sourcePort; guint16 destinationPort = tcpHeader.destinationPort; guint32 sequence = tcpHeader.sequence; guint32 acknowledgement = 0; if(tcpHeader.flags & PTCP_ACK) { acknowledgement = htonl(tcpHeader.acknowledgment); } guint8 headerLength = 0x80; guint8 tcpFlags = 0; if(tcpHeader.flags & PTCP_RST) tcpFlags |= 0x04; if(tcpHeader.flags & PTCP_SYN) tcpFlags |= 0x02; if(tcpHeader.flags & PTCP_ACK) tcpFlags |= 0x10; if(tcpHeader.flags & PTCP_FIN) tcpFlags |= 0x01; guint16 window = tcpHeader.window; guint16 tcpChecksum = 0x0000; guint8 options[14] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; fwrite(&sourcePort, 1, sizeof(sourcePort), pcap->pcapFile); fwrite(&destinationPort, 1, sizeof(destinationPort), pcap->pcapFile); fwrite(&sequence, 1, sizeof(sequence), pcap->pcapFile); fwrite(&acknowledgement, 1, sizeof(acknowledgement), pcap->pcapFile); fwrite(&headerLength, 1, sizeof(headerLength), pcap->pcapFile); fwrite(&tcpFlags, 1, sizeof(tcpFlags), pcap->pcapFile); fwrite(&window, 1, sizeof(window), pcap->pcapFile); fwrite(&tcpChecksum, 1, sizeof(tcpChecksum), pcap->pcapFile); fwrite(options, 1, sizeof(options), pcap->pcapFile); /* write payload data */ if(payloadLength > 0) { fwrite(payload, 1, payloadLength, pcap->pcapFile); } g_free(payload); }
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); } }