예제 #1
0
void cubic_congestionAvoidance(Cubic* cubic, gint inFlight, gint packetsAcked, gint ack) {
    MAGIC_ASSERT(cubic);
    TCPCongestion* congestion = (TCPCongestion*)cubic;

    gint32 now = worker_getCurrentTime() / SIMTIME_ONE_MILLISECOND;
    if(now - cubic->hystart.lastReset >= congestion->rttSmoothed) {
        _cubic_hystartReset(cubic, inFlight);
    }
    _cubic_hystartUpdate(cubic);

    if(congestion->window <= congestion->threshold) {
        congestion->state = TCP_CCS_SLOWSTART;
        congestion->window++;
    } else {
        congestion->state = TCP_CCS_AVOIDANCE;
        _cubic_update(cubic);

        if(cubic->windowCount > cubic->count) {
            congestion->window += 1;
            cubic->windowCount = 0;
        } else {
            cubic->windowCount += 1;
        }
    }
}
예제 #2
0
static void _cubic_hystartReset(Cubic* cubic, gint ack) {
    MAGIC_ASSERT(cubic);
    TCPCongestion* congestion = (TCPCongestion*)cubic;

    SimulationTime now = worker_getCurrentTime() / SIMTIME_ONE_MILLISECOND;
    cubic->hystart.roundStart = now;
    cubic->hystart.lastReset = now;
    cubic->hystart.lastTime = now;
    cubic->hystart.lastRTT = congestion->rttSmoothed;
    cubic->hystart.currRTT = 0;
    cubic->hystart.samplingCount = cubic->hystart.nSampling;
    cubic->hystart.endSequence = ack;
}
예제 #3
0
파일: shd-tracker.c 프로젝트: 4sp1r3/shadow
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);
}
예제 #4
0
static void _cubic_hystartUpdate(Cubic* cubic) {
    MAGIC_ASSERT(cubic);
    TCPCongestion* congestion = (TCPCongestion*)cubic;

    SimulationTime now = worker_getCurrentTime() / SIMTIME_ONE_MILLISECOND;
    gint rtt = congestion->rttSmoothed;
    if(!rtt) {
        rtt = 100;
    }

    gint delayMin = MIN(cubic->hystart.delayMin, rtt);

    if(!cubic->hystart.delayMin) {
        delayMin = rtt;
        cubic->hystart.delayMin = delayMin;
    }

    if(!cubic->hystart.found && congestion->window <= congestion->threshold) {
        if(now - cubic->hystart.lastTime <= 2) {
            cubic->hystart.lastTime = now;
            if(now - cubic->hystart.roundStart >= delayMin / 2) {
                cubic->hystart.found = 1;
            }
        }

        if(cubic->hystart.samplingCount) {
            cubic->hystart.currRTT = MIN(cubic->hystart.currRTT, rtt);
            if(!cubic->hystart.currRTT) {
                cubic->hystart.currRTT = rtt;
            }
            cubic->hystart.samplingCount--;
        }

        gint n = MAX(2, ceil(cubic->hystart.lastRTT / 16.0));
        if(!cubic->hystart.samplingCount && cubic->hystart.currRTT >= cubic->hystart.lastRTT + n) {
            cubic->hystart.found = 2;
        }

        if(cubic->hystart.found && congestion->window >= cubic->hystart.lowThreshold) {
            congestion->threshold = congestion->window;
        }
    }
}
예제 #5
0
void networkinterface_sent(NetworkInterface* interface) {
	MAGIC_ASSERT(interface);

	/* we just finished sending some packets */
	interface->flags &= ~NIF_SENDING;

	/* decide how much delay we get to absorb based on the passed time */
	SimulationTime now = worker_getCurrentTime();
	SimulationTime absorbInterval = now - interface->lastTimeSent;

	if(absorbInterval > 0) {
		gdouble newConsumed = interface->sendNanosecondsConsumed - absorbInterval;
		interface->sendNanosecondsConsumed = MAX(0, newConsumed);
	}

	interface->lastTimeSent = now;

	/* now try to send the next ones */
	_networkinterface_scheduleNextSend(interface);
}
예제 #6
0
void networkinterface_received(NetworkInterface* interface) {
	MAGIC_ASSERT(interface);

	/* we just finished receiving some packets */
	interface->flags &= ~NIF_RECEIVING;

	/* decide how much delay we get to absorb based on the passed time */
	SimulationTime now = worker_getCurrentTime();
	SimulationTime absorbInterval = now - interface->lastTimeReceived;

	if(absorbInterval > 0) {
		/* decide how much delay we get to absorb based on the passed time */
		gdouble newConsumed = interface->receiveNanosecondsConsumed - absorbInterval;
		interface->receiveNanosecondsConsumed = MAX(0, newConsumed);
	}

	interface->lastTimeReceived = now;

	/* now try to receive the next ones */
	_networkinterface_scheduleNextReceive(interface);
}
예제 #7
0
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);
}
예제 #8
0
static void _cubic_update(Cubic* cubic) {
    MAGIC_ASSERT(cubic);
    TCPCongestion* congestion = (TCPCongestion*)cubic;

    gint now = (gint)(worker_getCurrentTime() / SIMTIME_ONE_MILLISECOND);
    gint rtt = congestion->rttSmoothed;

    if(cubic->delayMin) {
        cubic->delayMin = MIN(cubic->delayMin, rtt);
    } else {
        cubic->delayMin = rtt;
    }

    cubic->ackCount += 1;

    if(now - cubic->lastTime <= HZ / 32) {
        return;
    }

    cubic->lastTime = now;

    if(!cubic->epochStart) {
        cubic->epochStart = now;
        if(congestion->window < cubic->lastMaxWindow) {
            cubic->k = cbrt(cubic->cubeFactor * (cubic->lastMaxWindow - congestion->window));
            cubic->originPoint = cubic->lastMaxWindow;
        } else {
            cubic->k = 0;
            cubic->originPoint = congestion->window;
        }
        cubic->ackCount = 1;
        cubic->tcpWindowEst = congestion->window;
    }
    
    gint t = now + cubic->delayMin - cubic->epochStart;
    gint64 offset = 0;
    if(t < cubic->k) {
        offset = cubic->k - t;
    } else {
        offset = t - cubic->k;
    }

    gint originDelta = (gint)((cubic->rttScale * offset * offset * offset) >> 40);
    gint target = 0;
    if(t < cubic->k) {
        target = cubic->originPoint - originDelta;
    } else {
        target = cubic->originPoint + originDelta;
    }
    
    if(target > congestion->window) {
        cubic->count = congestion->window / (target - congestion->window);
    } else {
        cubic->count = congestion->window * 100;
    }

    if(cubic->delayMin > 0) {
        gint minCount = (congestion->window * 1000 * 8) / (10 * 16 * cubic->delayMin);
        if(cubic->count < minCount && t >= cubic->k) {
            cubic->count = minCount;
        }
    }

    /* cubic_tcp_friendliness() */
    gint32 delta = (congestion->window * cubic->betaScale) >> 3;
    while (cubic->ackCount > delta) {       /* update tcp window */
        cubic->ackCount -= delta;
        cubic->tcpWindowEst++;
    }

    cubic->ackCount = 0;
    if(cubic->tcpWindowEst > congestion->window) {
        guint maxCount = congestion->window / (cubic->tcpWindowEst - congestion->window);
        if(cubic->count > maxCount) {
            cubic->count = maxCount;
        }
    }

    cubic->count /= 2;
    if(cubic->count == 0) {
        cubic->count = 1;
    }
}
예제 #9
0
파일: shd-logging.c 프로젝트: 4sp1r3/shadow
void logging_logv(const gchar *msgLogDomain, GLogLevelFlags msgLogLevel,
        const gchar* fileName, const gchar* functionName, const gint lineNumber,
        const gchar *format, va_list vargs) {
    /* this is called by worker threads, so we have access to worker */

    /* see if we can avoid some work because the message is filtered anyway */
    const gchar* logDomainStr = msgLogDomain ? msgLogDomain : "shadow";
    if(worker_isFiltered(msgLogLevel)) {
        return;
    }

    gchar* logFileStr = fileName ? g_path_get_basename(fileName) : g_strdup("n/a");
    const gchar* logFunctionStr = functionName ? functionName : "n/a";
    const gchar* formatStr = format ? format : "n/a";
    const gchar* logLevelStr = _logging_getNewLogLevelString(msgLogLevel);

    SimulationTime currentTime = worker_isAlive() ? worker_getCurrentTime() : SIMTIME_INVALID;
    Host* currentHost = worker_isAlive() ? worker_getCurrentHost() : NULL;
    gint workerThreadID = worker_isAlive() ? worker_getThreadID() : 0;

    /* format the simulation time if we are running an event */
    GString* clockStringBuffer = g_string_new("");
    if(currentTime != SIMTIME_INVALID) {
        SimulationTime hours, minutes, seconds, remainder;
        remainder = currentTime;

        hours = remainder / SIMTIME_ONE_HOUR;
        remainder %= SIMTIME_ONE_HOUR;
        minutes = remainder / SIMTIME_ONE_MINUTE;
        remainder %= SIMTIME_ONE_MINUTE;
        seconds = remainder / SIMTIME_ONE_SECOND;
        remainder %= SIMTIME_ONE_SECOND;

        g_string_printf(clockStringBuffer, "%02"G_GUINT64_FORMAT":%02"G_GUINT64_FORMAT":%02"G_GUINT64_FORMAT".%09"G_GUINT64_FORMAT"",
                hours, minutes, seconds, remainder);
    } else {
        g_string_printf(clockStringBuffer, "n/a");
    }

    /* we'll need to free clockString later */
    gchar* clockString = g_string_free(clockStringBuffer, FALSE);

    /* node identifier, if we are running a node
     * dont free this since we dont own the ip address string */
    GString* nodeStringBuffer = g_string_new("");
    if(currentHost) {
        g_string_printf(nodeStringBuffer, "%s~%s", host_getName(currentHost), host_getDefaultIPName(currentHost));
    } else {
        g_string_printf(nodeStringBuffer, "n/a");
    }
    gchar* nodeString = g_string_free(nodeStringBuffer, FALSE);

    /* the function name - no need to free this */
    GString* newLogFormatBuffer = g_string_new(NULL);
    g_string_printf(newLogFormatBuffer, "[thread-%i] %s [%s-%s] [%s] [%s:%i] [%s] %s",
            workerThreadID, clockString, logDomainStr, logLevelStr, nodeString,
            logFileStr, lineNumber, logFunctionStr, formatStr);

    /* get the new format out of our string buffer and log it */
    gchar* newLogFormat = g_string_free(newLogFormatBuffer, FALSE);
    g_logv(logDomainStr, msgLogLevel, newLogFormat, vargs);

    /* cleanup */
    g_free(logFileStr);
    g_free(newLogFormat);
    g_free(clockString);
    g_free(nodeString);
}