/*-----------------------------------------------------------------------------*/ void uip_split_output(void) { #if UIP_TCP u16_t tcplen, len1, len2; /* We only try to split maximum sized TCP segments. */ if(BUF->proto == UIP_PROTO_TCP && uip_len == UIP_BUFSIZE) { tcplen = uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN; /* Split the segment in two. If the original packet length was odd, we make the second packet one byte larger. */ len1 = len2 = tcplen / 2; if(len1 + len2 < tcplen) { ++len2; } /* Create the first packet. This is done by altering the length field of the IP header and updating the checksums. */ uip_len = len1 + UIP_TCPIP_HLEN + UIP_LLH_LEN; #if UIP_CONF_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else /* UIP_CONF_IPV6 */ BUF->len[0] = (uip_len - UIP_LLH_LEN) >> 8; BUF->len[1] = (uip_len - UIP_LLH_LEN) & 0xff; #endif /* UIP_CONF_IPV6 */ /* Recalculate the TCP checksum. */ BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); #if !UIP_CONF_IPV6 /* Recalculate the IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); #endif /* UIP_CONF_IPV6 */ /* Transmit the first packet. */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len); #endif /* UIP_CONF_IPV6 */ /* Now, create the second packet. To do this, it is not enough to just alter the length field, but we must also update the TCP sequence number and point the uip_appdata to a new place in memory. This place is determined by the length of the first packet (len1). */ uip_len = len2 + UIP_TCPIP_HLEN + UIP_LLH_LEN; #if UIP_CONF_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else /* UIP_CONF_IPV6 */ BUF->len[0] = (uip_len - UIP_LLH_LEN) >> 8; BUF->len[1] = (uip_len - UIP_LLH_LEN) & 0xff; #endif /* UIP_CONF_IPV6 */ memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2); uip_add32(BUF->seqno, len1); BUF->seqno[0] = uip_acc32[0]; BUF->seqno[1] = uip_acc32[1]; BUF->seqno[2] = uip_acc32[2]; BUF->seqno[3] = uip_acc32[3]; /* Recalculate the TCP checksum. */ BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); #if !UIP_CONF_IPV6 /* Recalculate the IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); #endif /* UIP_CONF_IPV6 */ /* Transmit the second packet. */ #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len); #endif /* UIP_CONF_IPV6 */ return; }
/*-----------------------------------------------------------------------------*/ void uip_split_output(chanend mac_tx) { u16_t tcplen, len1, len2; /* We only try to split maximum sized TCP segments. */ if(BUF->proto == UIP_PROTO_TCP && uip_len + UIP_TCPIP_HLEN > UIP_BUFSIZE/2) { // printstr("split"); tcplen = uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN; /* Split the segment in two. If the original packet length was odd, we make the second packet one byte larger. */ len1 = len2 = tcplen / 2; if(len1 + len2 < tcplen) { ++len2; } /* Create the first packet. This is done by altering the length field of the IP header and updating the checksums. */ uip_len = len1 + UIP_TCPIP_HLEN; #if UIP_CONF_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else /* UIP_CONF_IPV6 */ BUF->len[0] = uip_len >> 8; BUF->len[1] = uip_len & 0xff; #endif /* UIP_CONF_IPV6 */ /* Recalculate the TCP checksum. */ BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); #if !UIP_CONF_IPV6 /* Recalculate the IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); #endif /* UIP_CONF_IPV6 */ uip_len += UIP_LLH_LEN; /* Transmit the first packet. */ /* uip_fw_output();*/ /* tcpip_output(); */ xcoredev_send(mac_tx); /* Now, create the second packet. To do this, it is not enough to just alter the length field, but we must also update the TCP sequence number and point the uip_appdata to a new place in memory. This place is detemined by the length of the first packet (len1). */ uip_len = len2 + UIP_TCPIP_HLEN; #if UIP_CONF_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else /* UIP_CONF_IPV6 */ BUF->len[0] = uip_len >> 8; BUF->len[1] = uip_len & 0xff; #endif /* UIP_CONF_IPV6 */ /* uip_appdata += len1;*/ memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2); uip_add32(BUF->seqno, len1); BUF->seqno[0] = uip_acc32[0]; BUF->seqno[1] = uip_acc32[1]; BUF->seqno[2] = uip_acc32[2]; BUF->seqno[3] = uip_acc32[3]; /* Recalculate the TCP checksum. */ BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); #if !UIP_CONF_IPV6 /* Recalculate the IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); #endif /* UIP_CONF_IPV6 */ /* Transmit the second packet. */ /* uip_fw_output();*/ /*tcpip_output();*/ uip_len += UIP_LLH_LEN; xcoredev_send(mac_tx); } else {
// The purpose of this function is to defeat Neagles Algorithm. For packets // over half of the size of the max frame size (which we assume to be part of // a data stream and therefore need to be ACKed quickly) we break the packet // in two, which means that the Neagles Algorithm effect of ACKing only every // other packet will generate ACKs for us for each transmission. // // Without this, since we do not have a sliding window, and therefore do not // transmit packet 2 until packet 1 has been acknowledged, we have to wait // until the other end times out of the 300ms delay before sending us an ACK. void uip_split_output(chanend mac_tx) { u16_t tcplen, len1, len2; if (BUF->proto == UIP_PROTO_TCP) { int data_len = uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN; if (data_len > ACTUAL_UIP_PACKET_SPLIT_THRESHOLD) { tcplen = uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN; /* Split the segment in two, making sure the first segment is an * integer number of words */ len1 = (tcplen / 2) & ~3; len2 = tcplen - len1; /* Create the first packet. This is done by altering the length field of the IP header and updating the checksums. */ uip_len = len1 + UIP_TCPIP_HLEN; #if UIP_CONF_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else BUF->len[0] = uip_len >> 8; BUF->len[1] = uip_len & 0xff; #endif uip_split_output_send(mac_tx); /* Now, create the second packet. To do this, it is not enough to just alter the length field, but we must also update the TCP sequence number and point the uip_appdata to a new place in memory. This place is determined by the length of the first packet (len1). */ uip_len = len2 + UIP_TCPIP_HLEN; #if UIP_CONF_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else BUF->len[0] = uip_len >> 8; BUF->len[1] = uip_len & 0xff; #endif /* Sadly we must copy the packet contents down to the bottom of the packet. * * We know that the data sections are on a short word boundary, and not * on a word boundary */ ((u16_t*) uip_appdata)[0] = ((u16_t *) (uip_appdata + len1))[0]; { unsigned* dst = (unsigned*) (uip_appdata + 2); unsigned* src = (unsigned*) (uip_appdata + 2 + len1); for (unsigned i = 0; i < (len2 / 4 + 1); ++i) { dst[i] = src[i]; } } uip_add32(BUF->seqno, len1); xtcp_copy_word(BUF->seqno, uip_acc32); uip_split_output_send(mac_tx); } else {
/*-----------------------------------------------------------------------------*/ void uip_split_output(void) { #if UIP_TCP uint16_t tcplen, len1, len2; /* We only split TCP segments that are larger than or equal to UIP_SPLIT_SIZE, which is configurable through UIP_SPLIT_CONF_SIZE. */ if(BUF->proto == UIP_PROTO_TCP && uip_len >= UIP_SPLIT_SIZE + UIP_TCPIP_HLEN) { tcplen = uip_len - UIP_TCPIP_HLEN; /* Split the segment in two. If the original packet length was odd, we make the second packet one byte larger. */ len1 = len2 = tcplen / 2; if(len1 + len2 < tcplen) { ++len2; } /* Create the first packet. This is done by altering the length field of the IP header and updating the checksums. */ uip_len = len1 + UIP_TCPIP_HLEN; #if NETSTACK_CONF_WITH_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else /* NETSTACK_CONF_WITH_IPV6 */ BUF->len[0] = uip_len >> 8; BUF->len[1] = uip_len & 0xff; #endif /* NETSTACK_CONF_WITH_IPV6 */ /* Recalculate the TCP checksum. */ BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); #if !NETSTACK_CONF_WITH_IPV6 /* Recalculate the IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); #endif /* NETSTACK_CONF_WITH_IPV6 */ /* Transmit the first packet. */ /* uip_fw_output();*/ #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else tcpip_output(); #endif /* NETSTACK_CONF_WITH_IPV6 */ /* Now, create the second packet. To do this, it is not enough to just alter the length field, but we must also update the TCP sequence number and point the uip_appdata to a new place in memory. This place is detemined by the length of the first packet (len1). */ uip_len = len2 + UIP_TCPIP_HLEN; #if NETSTACK_CONF_WITH_IPV6 /* For IPv6, the IP length field does not include the IPv6 IP header length. */ BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); #else /* NETSTACK_CONF_WITH_IPV6 */ BUF->len[0] = uip_len >> 8; BUF->len[1] = uip_len & 0xff; #endif /* NETSTACK_CONF_WITH_IPV6 */ /* uip_appdata += len1;*/ memcpy(uip_appdata, (uint8_t *)uip_appdata + len1, len2); uip_add32(BUF->seqno, len1); BUF->seqno[0] = uip_acc32[0]; BUF->seqno[1] = uip_acc32[1]; BUF->seqno[2] = uip_acc32[2]; BUF->seqno[3] = uip_acc32[3]; /* Recalculate the TCP checksum. */ BUF->tcpchksum = 0; BUF->tcpchksum = ~(uip_tcpchksum()); #if !NETSTACK_CONF_WITH_IPV6 /* Recalculate the IP checksum. */ BUF->ipchksum = 0; BUF->ipchksum = ~(uip_ipchksum()); #endif /* NETSTACK_CONF_WITH_IPV6 */ /* Transmit the second packet. */ /* uip_fw_output();*/ #if NETSTACK_CONF_WITH_IPV6 tcpip_ipv6_output(); #else tcpip_output(); #endif /* NETSTACK_CONF_WITH_IPV6 */ return; }