#ifndef CLICK_IPFRAGMENTER_HH
#define CLICK_IPFRAGMENTER_HH
#include <click/element.hh>
#include <click/glue.hh>
#include <click/atomic.hh>
CLICK_DECLS

/*
 * =c
 * IPFragmenter(MTU, [I<keywords> HONOR_DF, VERBOSE])
 * =s ip
 * fragments large IP packets
 * =d
 *
 * Expects IP packets as input. If the IP packet size is <= MTU, just emits
 * the packet on output 0. If the size is greater than MTU and the
 * don't-fragment bit (DF) isn't set, IPFragmenter splits the packet into
 * fragments emitted on output 0. If DF is set and the packet size is greater
 * than MTU, sends the packet to output 1 (but see HONOR_DF below). Ordinarily
 * output 1 is connected to an ICMPError element with type 3 (UNREACH) and
 * code 4 (NEEDFRAG).
 *
 * Only the mac_broadcast annotation is copied into the fragments.
 *
 * Sends the first fragment last.
 *
 * Keyword arguments are:
 *
 * =over 8
 *
 * =item HONOR_DF
 *
 * Boolean. If HONOR_DF is false, IPFragmenter will ignore the don't-fragment
 * (DF) bit and fragment every packet larger than MTU. Default is true.
 *
 * =item VERBOSE
 *
 * Boolean.  If true, IPFragmenter will print a message every time it sees a
 * packet with DF; otherwise, it will print a message only the first 5 times.
 * Default is false.
 *
 * =e
 *   ... -> fr::IPFragmenter(1024) -> Queue(20) -> ...
 *   fr[1] -> ICMPError(18.26.4.24, 3, 4) -> ...
 *
 * =a ICMPError, CheckLength
 */

class IPFragmenter : public Element { public:

  IPFragmenter();
  ~IPFragmenter();
  
  const char *class_name() const		{ return "IPFragmenter"; }
  const char *port_count() const		{ return "1/1-2"; }
  const char *processing() const		{ return PUSH; }
  int configure(Vector<String> &, ErrorHandler *);
  
  uint32_t drops() const			{ return _drops; }
  uint32_t fragments() const			{ return _fragments; }
  
  void add_handlers();

  void push(int, Packet *);

 private:

  bool _honor_df;
  bool _verbose;
  unsigned _mtu;
  atomic_uint32_t _drops;
  atomic_uint32_t _fragments;

  void fragment(Packet *);
  int optcopy(const click_ip *ip1, click_ip *ip2);
  
};

CLICK_ENDDECLS
#endif


syntax highlighted by Code2HTML, v. 0.9.1