Skip to content

Commit

Permalink
Merge pull request #9 from appneta/Enhancement_pseudo_crc
Browse files Browse the repository at this point in the history
Enhancement pseudo crc
  • Loading branch information
fklassen committed Dec 5, 2013
2 parents 8481a8a + 5f029c3 commit d3eb0a7
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 21 deletions.
4 changes: 3 additions & 1 deletion docs/CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
$Id$

??/??/2013 Version 3.5.0
- Removed sleep-accel option (anneta #2)
- Implement pseudo-CRC to improve tcpedit performance (appneta #8)
- Add --fast-flows option to tcpreplay (appneta #4)
- Removed sleep-accel option (appneta #2)
- Enhance accuracy and performance of --mbps option (appneta #2)
- Add netmap injector (appneta #1)
- Add --sleepmode option to handle high precision timing (#421)
Expand Down
8 changes: 6 additions & 2 deletions docs/CREDIT
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
$Id$

tcpreplay and it's associated utilities (tcpprep, tcprewrite and flowreplay)
were designed and written by Aaron Turner.
were designed and written by Aaron Turner, and maintained by Fred Klassen
of AppNeta Inc.

This product includes software developed by the University of California,
Berkeley, Lawrence Berkeley Laboratory and its contributors.
Expand Down Expand Up @@ -57,7 +58,10 @@ Bojan Smojver <[email protected]>
Stas Grabois <[email protected]>
- For his efforts to add IPv6 support to tcpprep and the tcpedit engine
- For adding IPv6 support to fragroute

Fred Klassen - AppNeta Inc. <fklassen at appneta dot com>
- Added netmap support for wire-rate performance on commodity hardware
- Improve accuracy and performance of the --mbps option
- Implement pseudo-CRC to improve tcpedit performance
- Add --fast-flows option to tcpreplay

12 changes: 6 additions & 6 deletions src/send_packets.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ send_packets(pcap_t *pcap, int cache_file_idx)
#endif
#if defined TCPREPLAY && !defined TCPREPLAY_EDIT
static u_int32_t iteration = 0;
int datalink = options.int1dlt;
int datalink = options.intf1dlt;
#endif
COUNTER skip_length = 0;
COUNTER start_us;
Expand Down Expand Up @@ -401,7 +401,7 @@ send_dual_packets(pcap_t *pcap1, int cache_file_idx1, pcap_t *pcap2, int cache_f
struct pcap_pkthdr *pkthdr_ptr;
#if defined TCPREPLAY && !defined TCPREPLAY_EDIT
static u_int32_t iteration = 0;
int datalink = options.int1dlt;
int datalink = options.intf1dlt;
#endif
COUNTER start_us;
COUNTER skip_length = 0;
Expand Down Expand Up @@ -456,7 +456,7 @@ send_dual_packets(pcap_t *pcap1, int cache_file_idx1, pcap_t *pcap2, int cache_f
/* file 2 is next */
sp = options.intf2;
#if defined TCPREPLAY && !defined TCPREPLAY_EDIT
datalink = options.int2dlt;
datalink = options.intf2dlt;
#endif
pcap = pcap2;
pkthdr_ptr = &pkthdr2;
Expand All @@ -467,7 +467,7 @@ send_dual_packets(pcap_t *pcap1, int cache_file_idx1, pcap_t *pcap2, int cache_f
/* file 1 is next */
sp = options.intf1;
#if defined TCPREPLAY && !defined TCPREPLAY_EDIT
datalink = options.int1dlt;
datalink = options.intf1dlt;
#endif
pcap = pcap1;
pkthdr_ptr = &pkthdr1;
Expand All @@ -478,7 +478,7 @@ send_dual_packets(pcap_t *pcap1, int cache_file_idx1, pcap_t *pcap2, int cache_f
/* file 1 is next */
sp = options.intf1;
#if defined TCPREPLAY && !defined TCPREPLAY_EDIT
datalink = options.int1dlt;
datalink = options.intf1dlt;
#endif
pcap = pcap1;
pkthdr_ptr = &pkthdr1;
Expand All @@ -489,7 +489,7 @@ send_dual_packets(pcap_t *pcap1, int cache_file_idx1, pcap_t *pcap2, int cache_f
/* file 2 is next */
sp = options.intf2;
#if defined TCPREPLAY && !defined TCPREPLAY_EDIT
datalink = options.int2dlt;
datalink = options.intf2dlt;
#endif
pcap = pcap2;
pkthdr_ptr = &pkthdr2;
Expand Down
49 changes: 49 additions & 0 deletions src/tcpedit/checksum.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,55 @@

static int do_checksum_math(u_int16_t *, int);

/*
* Fold a partial checksum
*
* shamelessly stolen from Linux kernel and modified
* to run in user land
*/
static inline u_int16_t csum_fold(u_int32_t csum)
{
u_int32_t sum = csum;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
return (u_int16_t)~sum;
}

static inline u_int32_t csum_partial(void *buff, int len, u_int32_t wsum)
{
unsigned int sum = (unsigned int)wsum;
unsigned int result = do_checksum_math(buff, len);

/* add in old sum, and carry.. */
result += sum;
if (sum > result)
result += 1;
return (u_int32_t)result;
}

static inline void __chksum_replace4(u_int16_t *sum, u_int32_t from, u_int32_t to)
{
u_int32_t diff[] = { ~from, to };
*sum = csum_fold(csum_partial(diff, sizeof(diff), ~((u_int32_t)(*sum))));
}

/**
* Apply modifications to an existing checksum based on
* 32-bit before and after values
*/
void chksum_replace4(u_int16_t *sum, u_int32_t from, u_int32_t to)
{
__chksum_replace4(sum, from, to);
}

/**
* Apply modifications to an existing checksum based on
* 32-bit before and after values
*/
void chksum_replace2(u_int16_t *sum, u_int16_t from, u_int16_t to)
{
__chksum_replace4(sum, (u_int32_t)from, (u_int32_t)to);
}

/**
* Returns -1 on error and 0 on success, 1 on warn
Expand Down
2 changes: 2 additions & 0 deletions src/tcpedit/checksum.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,7 @@
(x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff))

int do_checksum(tcpedit_t *, u_int8_t *, int, int);
void chksum_replace4(u_int16_t *sum, u_int32_t from, u_int32_t to);
void ckksum_replace2(u_int16_t *sum, u_int16_t from, u_int16_t to);

#endif
76 changes: 73 additions & 3 deletions src/tcpedit/edit_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,70 @@ fix_ipv6_checksums(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr, ipv6_hdr_t *i
return TCPEDIT_OK;
}

#define IP_DF 0x4000 /* Flag: "Don't Fragment" */
#define IP_MF 0x2000 /* Flag: "More Fragments" */
#define IP_OFFSET 0x1FFF /* "Fragment Offset" part */
int chksum_replace_ipv4(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr, u_int32_t from, u_int32_t to)
{
if (tcpedit->fixcsum == TCPEDIT_FIXCSUM_DISABLE)
return 0;

chksum_replace4(&ip_hdr->ip_sum, from, to);
return 0;
}

static int transport_pseudo_chksum_ipv4(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr,
u_int32_t from, u_int32_t to)
{
int ihl;
u_char *transport;
u_int8_t protocol;

if (tcpedit->fixcsum == TCPEDIT_FIXCSUM_DISABLE)
return 0;

ihl = ip_hdr->ip_hl * 4;
transport = ((u_char *)ip_hdr) + ihl;
protocol = ip_hdr->ip_p;

chksum_replace4(&ip_hdr->ip_sum, from, to);

/* reject IP fragments */
if (ip_hdr->ip_off & htons(IP_OFFSET))
return 1;

switch (protocol) {
case IPPROTO_TCP:
{
struct tcpr_tcp_hdr *tcph;

tcph = (struct tcpr_tcp_hdr *)transport;
chksum_replace4(&tcph->th_sum, from, to);
break;
}
case IPPROTO_UDP:
{
struct tcpr_udp_hdr *udph;

udph = (struct tcpr_udp_hdr *)transport;
if (udph->uh_sum) {
chksum_replace4(&udph->uh_sum, from, to);
if (!udph->uh_sum)
udph->uh_sum = 0xffff; /* mangled checksum */
}
break;
}

case IPPROTO_ICMP:
break;

default:
return 1;
}

return 0;
}

/**
* returns a new 32bit integer which is the randomized IP
* based upon the user specified seed
Expand Down Expand Up @@ -170,6 +234,8 @@ randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,
#ifdef DEBUG
char srcip[16], dstip[16];
#endif
int needtorecalc = 0;

assert(tcpedit);
assert(pkthdr);
assert(pktdata);
Expand All @@ -185,13 +251,17 @@ randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,

/* don't rewrite broadcast addresses */
if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_dst.s_addr))
|| !tcpedit->skip_broadcast) {
|| !tcpedit->skip_broadcast) {
in_addr_t old_dst_ip = ip_hdr->ip_dst.s_addr;
ip_hdr->ip_dst.s_addr = randomize_ipv4_addr(tcpedit, ip_hdr->ip_dst.s_addr);
needtorecalc += transport_pseudo_chksum_ipv4(tcpedit, ip_hdr, old_dst_ip, ip_hdr->ip_dst.s_addr);
}

if ((tcpedit->skip_broadcast && is_unicast_ipv4(tcpedit, (u_int32_t)ip_hdr->ip_src.s_addr))
|| !tcpedit->skip_broadcast) {
|| !tcpedit->skip_broadcast) {
in_addr_t old_src_ip = ip_hdr->ip_src.s_addr;
ip_hdr->ip_src.s_addr = randomize_ipv4_addr(tcpedit, ip_hdr->ip_src.s_addr);
needtorecalc += transport_pseudo_chksum_ipv4(tcpedit, ip_hdr, old_src_ip, ip_hdr->ip_src.s_addr);
}

#ifdef DEBUG
Expand All @@ -201,7 +271,7 @@ randomize_ipv4(tcpedit_t *tcpedit, struct pcap_pkthdr *pkthdr,

dbgx(1, "New Src IP: %s\tNew Dst IP: %s\n", srcip, dstip);

return(1);
return(needtorecalc);
}

int
Expand Down
2 changes: 2 additions & 0 deletions src/tcpedit/edit_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ int rewrite_ipv4_ttl(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr);

int rewrite_ipv6_hlim(tcpedit_t *tcpedit, ipv6_hdr_t *ip6_hdr);

int chksum_replace_ipv4(tcpedit_t *tcpedit, ipv4_hdr_t *ip_hdr, u_int32_t from, u_int32_t to);

#define BROADCAST_IP 4294967295

#endif
Expand Down
5 changes: 4 additions & 1 deletion src/tcpedit/tcpedit.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,16 +278,19 @@ tcpedit_packet(tcpedit_t *tcpedit, struct pcap_pkthdr **pkthdr,
if ((tcpedit->fixcsum == TCPEDIT_FIXCSUM_ON ||
(needtorecalc && tcpedit->fixcsum != TCPEDIT_FIXCSUM_DISABLE))) {
if (ip_hdr != NULL) {
dbgx(3, "doing IPv4 checksum: needtorecalc=%d", needtorecalc);
retval = fix_ipv4_checksums(tcpedit, *pkthdr, ip_hdr);
} else if (ip6_hdr != NULL) {
dbgx(3, "doing IPv6 checksum: needtorecalc=%d", needtorecalc);
retval = fix_ipv6_checksums(tcpedit, *pkthdr, ip6_hdr);
} else {
dbgx(3, "checksum not performed: needtorecalc=%d", needtorecalc);
retval = TCPEDIT_OK;
}
if (retval < 0) {
return TCPEDIT_ERROR;
} else if (retval == TCPEDIT_WARN) {
warnx("%s", tcpedit_getwarn(tcpedit));
dbgx(3, "%s", tcpedit_getwarn(tcpedit));
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/tcpreplay.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ replay_file(int file_idx)


if (pcap != NULL) {
dlt = sendpacket_get_dlt(options.intf1);
dlt = options.intf1dlt;
if ((dlt > 0) && (dlt != pcap_datalink(pcap)))
warnx("%s DLT (%s) does not match that of the outbound interface: %s (%s)",
path, pcap_datalink_val_to_name(pcap_datalink(pcap)),
Expand Down Expand Up @@ -606,7 +606,7 @@ post_args(int argc)
if ((options.intf1 = sendpacket_open(options.intf1_name, ebuf, TCPR_DIR_C2S, sendpacket_type)) == NULL)
errx(-1, "Can't open %s: %s", options.intf1_name, ebuf);

options.int1dlt = sendpacket_get_dlt(options.intf1);
options.intf1dlt = sendpacket_get_dlt(options.intf1);

if (HAVE_OPT(INTF2)) {
if (! HAVE_OPT(CACHEFILE) && ! HAVE_OPT(DUALFILE))
Expand All @@ -621,11 +621,11 @@ post_args(int argc)
if ((options.intf2 = sendpacket_open(options.intf2_name, ebuf, TCPR_DIR_S2C, sendpacket_type)) == NULL)
errx(-1, "Can't open %s: %s", options.intf2_name, ebuf);

options.int2dlt = sendpacket_get_dlt(options.intf2);
if (options.int2dlt != options.int1dlt)
options.intf2dlt = sendpacket_get_dlt(options.intf2);
if (options.intf2dlt != options.intf1dlt)
errx(-1, "DLT type missmatch for %s (%s) and %s (%s)",
options.intf1_name, pcap_datalink_val_to_name(options.int1dlt),
options.intf2_name, pcap_datalink_val_to_name(options.int2dlt));
options.intf1_name, pcap_datalink_val_to_name(options.intf1dlt),
options.intf2_name, pcap_datalink_val_to_name(options.intf2dlt));
}

if (HAVE_OPT(CACHEFILE)) {
Expand Down
4 changes: 2 additions & 2 deletions src/tcpreplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ struct tcpreplay_opt_s {
char *intf2_name;
sendpacket_t *intf1;
sendpacket_t *intf2;
int int1dlt;
int int2dlt;
int intf1dlt;
int intf2dlt;


tcpr_speed_t speed;
Expand Down

0 comments on commit d3eb0a7

Please sign in to comment.