I am planning on adding this element to click. If anyone has any comments/feedback on it, let me know.
Cliff
From 1e1a52e7aa6aa08e362210ba705bac7ca0d5e134 Mon Sep 17 00:00:00 2001 From: Cliff Frey <cl...@meraki.com> Date: Wed, 29 Sep 2010 15:55:10 -0700 Subject: [PATCH] add TCPFragmenter element This splits large TCP datagrams into smaller ones, it is useful for testing tcp stream processing. --- elements/tcpudp/tcpfragmenter.cc | 111 ++++++++++++++++++++++++++++++++++++++ elements/tcpudp/tcpfragmenter.hh | 45 +++++++++++++++ 2 files changed, 156 insertions(+), 0 deletions(-) create mode 100644 elements/tcpudp/tcpfragmenter.cc create mode 100644 elements/tcpudp/tcpfragmenter.hh diff --git a/elements/tcpudp/tcpfragmenter.cc b/elements/tcpudp/tcpfragmenter.cc new file mode 100644 index 0000000..d15d1da --- /dev/null +++ b/elements/tcpudp/tcpfragmenter.cc @@ -0,0 +1,111 @@ +/* + * tcpipencap.{cc,hh} -- element encapsulates packet in TCP/IP header + * Cliff Frey + * + * Copyright (c) 2010 Meraki, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, subject to the conditions + * listed in the Click LICENSE file. These conditions include: you must + * preserve this copyright notice, and you cannot mention the copyright + * holders in advertising related to the Software without their permission. + * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This + * notice is a summary of the Click LICENSE file; the license in that file is + * legally binding. + */ + +#include <click/config.h> +#include <clicknet/ip.h> +#include <clicknet/tcp.h> +#include "tcpfragmenter.hh" +#include <click/confparse.hh> +#include <click/error.hh> +#include <click/glue.hh> +#include <click/standard/alignmentinfo.hh> +#ifdef CLICK_LINUXMODULE +# include <net/checksum.h> +#endif +CLICK_DECLS + +TCPFragmenter::TCPFragmenter() +{ +} + +TCPFragmenter::~TCPFragmenter() +{ +} + +int +TCPFragmenter::configure(Vector<String> &conf, ErrorHandler *errh) +{ + uint16_t mtu; + if (cp_va_kparse(conf, this, errh, + "MTU", cpkP+cpkM, cpUnsignedShort, &mtu, + cpEnd) < 0) + return -1; + + if (mtu == 0) + return errh->error("MTU cannot be 0"); + + _mtu = mtu; + + return 0; +} + +void +TCPFragmenter::push(int, Packet *p) +{ + int32_t tcp_len; + { + const click_ip *ip = reinterpret_cast<const click_ip *>(p->network_header()); + const click_tcp *tcp = reinterpret_cast<const click_tcp *>(ip + 1); + tcp_len = (ntohs(ip->ip_len)-(ip->ip_hl<<2)-(tcp->th_off<<2)); + + if (!_mtu || tcp_len < _mtu) { + output(0).push(p); + return; + } + } + + for (int offset = 0; offset < tcp_len; offset += _mtu) { + Packet *p_clone; + if (offset + _mtu < tcp_len) + p_clone = p->clone(); + else { + p_clone = p; + p = 0; + } + if (!p_clone) + break; + WritablePacket *q = p_clone->uniqueify(); + p_clone = 0; + click_ip *ip = reinterpret_cast<click_ip *>(q->network_header()); + click_tcp *tcp = reinterpret_cast<click_tcp *>(ip + 1); + uint8_t *tcp_data = ((uint8_t *)tcp) + (tcp->th_off<<2); + int this_len = tcp_len - offset > _mtu ? _mtu : tcp_len - offset; + if (offset != 0) + memcpy(tcp_data, tcp_data + offset, this_len); + q->take(tcp_len - this_len); + ip->ip_len = htons(q->end_data() - q->network_header()); + ip->ip_sum = 0; +#if HAVE_FAST_CHECKSUM + ip->ip_sum = ip_fast_csum((unsigned char *)ip, sizeof(click_ip) >> 2); +#else + ip->ip_sum = click_in_cksum((unsigned char *)ip, sizeof(click_ip)); +#endif + + tcp->th_seq = htonl(ntohl(tcp->th_seq) + offset); + tcp->th_sum = 0; + + // now calculate tcp header cksum + int plen = q->end_data() - (uint8_t*)tcp; + unsigned csum = click_in_cksum((unsigned char *)tcp, plen); + tcp->th_sum = click_in_cksum_pseudohdr(csum, ip, plen); + output(0).push(q); + } +} + +CLICK_ENDDECLS +EXPORT_ELEMENT(TCPFragmenter) +ELEMENT_MT_SAFE(TCPFragmenter) diff --git a/elements/tcpudp/tcpfragmenter.hh b/elements/tcpudp/tcpfragmenter.hh new file mode 100644 index 0000000..f9b1feb --- /dev/null +++ b/elements/tcpudp/tcpfragmenter.hh @@ -0,0 +1,45 @@ +#ifndef CLICK_TCPFRAGMENTER_HH +#define CLICK_TCPFRAGMENTER_HH +#include <click/element.hh> +CLICK_DECLS + +/* +=c + +TCPFragmenter(MTU) + +=s tcp + +fragments TCP packets to a maximum TCP payload size + +=d + +TCP Packets with payload length greater than the MTU are fragmented into +multiple packets each containing at most MTU bytes of TCP payload. Each of +these new packets will be a copy of the input packet except for checksums (ip +and tcp), length (ip length), and tcp sequence number (for all fragments except +the first). + +=a IPFragmenter, TCPIPEncap +*/ + +class TCPFragmenter : public Element { public: + + TCPFragmenter(); + ~TCPFragmenter(); + + const char *class_name() const { return "TCPFragmenter"; } + const char *port_count() const { return PORTS_1_1; } + const char *processing() const { return PUSH; } + bool can_live_reconfigure() const { return true; } + + int configure(Vector<String> &, ErrorHandler *); + + void push(int, Packet *); + + private: + uint16_t _mtu; +}; + +CLICK_ENDDECLS +#endif -- 1.7.3
_______________________________________________ click mailing list click@amsterdam.lcs.mit.edu https://amsterdam.lcs.mit.edu/mailman/listinfo/click