...
 
Commits (3)
......@@ -40,6 +40,7 @@ GTPTable::configure(Vector<String> &conf, ErrorHandler *errh)
{
if (Args(conf, this, errh)
.read_mp("PING_DST",_ping_dst)
.read("VERBOSE", _verbose)
.complete() < 0)
return -1;
......
......@@ -92,8 +92,16 @@ update_in_cksum(uint16_t *csum, const uint16_t *old_hw, const uint16_t *new_hw,
}
int
ICMPRewriter::handle(WritablePacket *p)
ICMPRewriter::handle(Packet* &p_in)
{
WritablePacket *p = p_in->uniqueify();
if (!p)
return -1;
else if (p->ip_header()->ip_p != IP_PROTO_ICMP) {
return noutputs();
}
p_in = p;
// check ICMP type
click_icmp *icmph = p->icmp_header();
if (icmph->icmp_type != ICMP_UNREACH
......@@ -230,17 +238,18 @@ ICMPRewriter::handle(WritablePacket *p)
void
ICMPRewriter::push(int, Packet *p_in)
{
WritablePacket *p = p_in->uniqueify();
if (!p)
return;
else if (p->ip_header()->ip_p != IP_PROTO_ICMP) {
p->kill();
return;
}
int output = handle(p_in);
if (output == -1)
return;
checked_output_push(output, p_in);
}
int output = handle(p);
checked_output_push(output, p);
#if HAVE_BATCH
void
ICMPRewriter::push_batch(int, PacketBatch *batch) {
CLASSIFY_EACH_PACKET_IGNORE(noutputs() + 1,handle,batch,checked_output_push_batch);
}
#endif
CLICK_ENDDECLS
ELEMENT_REQUIRES(IPRewriterBase ICMPPingRewriter)
......
#ifndef CLICK_ICMPREWRITER_HH
#define CLICK_ICMPREWRITER_HH
#include <click/element.hh>
#include <click/batchelement.hh>
#include <clicknet/udp.h>
#include <clicknet/icmp.h>
#include "elements/ip/iprewriterbase.hh"
......@@ -58,7 +58,7 @@ ICMPPingRewriter, or other related classes.
IPAddrRewriter, IPRewriter, ICMPPingRewriter, TCPRewriter */
class ICMPRewriter : public Element { public:
class ICMPRewriter : public BatchElement { public:
ICMPRewriter() CLICK_COLD;
~ICMPRewriter() CLICK_COLD;
......@@ -70,7 +70,9 @@ class ICMPRewriter : public Element { public:
int configure(Vector<String> &, ErrorHandler *) CLICK_COLD;
void push(int, Packet *);
#if HAVE_BATCH
void push_batch(int, PacketBatch *);
#endif
protected:
struct MapEntry {
......@@ -91,7 +93,7 @@ class ICMPRewriter : public Element { public:
void rewrite_ping_packet(WritablePacket *, click_ip *, click_icmp_echo *,
const IPFlowID &, IPRewriterEntry *);
int handle(WritablePacket *p);
int handle(Packet* &p);
};
......
......@@ -496,9 +496,10 @@ KernelTun::cleanup(CleanupStage)
void
KernelTun::selected(int fd, int)
{
Timestamp now = Timestamp::now();
if (fd != _fd)
return;
Timestamp now = Timestamp::now();
++_selected_calls;
unsigned n = _burst;
#if HAVE_BATCH
......@@ -531,7 +532,7 @@ KernelTun::selected(int fd, int)
#endif
}
bool
int
KernelTun::one_selected(const Timestamp &now, WritablePacket* &p)
{
p = Packet::make(_headroom, 0, _mtu_in, 0);
......@@ -560,9 +561,9 @@ KernelTun::one_selected(const Timestamp &now, WritablePacket* &p)
p->pull(4);
if (etype != htons(ETHERTYPE_IP) && etype != htons(ETHERTYPE_IP6)) {
#if HAVE_BATCH
checked_output_push(1, p->clone());
#else
checked_output_push_batch(1, PacketBatch::make_from_packet(p->clone()));
#else
checked_output_push(1, p->clone());
#endif
} else
ok = fake_pcap_force_ip(p, FAKE_DLT_RAW);
......@@ -573,9 +574,9 @@ KernelTun::one_selected(const Timestamp &now, WritablePacket* &p)
if (af != AF_INET && af != AF_INET6) {
click_chatter("KernelTun(%s): don't know AF %d", _dev_name.c_str(), af);
#if HAVE_BATCH
checked_output_push(1, p->clone());
#else
checked_output_push_batch(1, PacketBatch::make_from_packet(p->clone()));
#else
checked_output_push(1, p->clone());
#endif
} else
ok = fake_pcap_force_ip(p, FAKE_DLT_RAW);
......@@ -586,7 +587,11 @@ KernelTun::one_selected(const Timestamp &now, WritablePacket* &p)
uint16_t etype = *(uint16_t *)(p->data() + 14);
p->pull(16);
if (etype != htons(ETHERTYPE_IP) && etype != htons(ETHERTYPE_IP6))
return 1;
#if HAVE_BATCH
checked_output_push_batch(1, PacketBatch::make_from_packet(p->clone()));
#else
checked_output_push(1, p->clone());
#endif
else
ok = fake_pcap_force_ip(p, FAKE_DLT_RAW);
}
......
......@@ -168,7 +168,7 @@ class KernelTun : public BatchElement { public:
int alloc_tun(ErrorHandler *);
int setup_tun(ErrorHandler *);
int updown(IPAddress, IPAddress, ErrorHandler *);
bool one_selected(const Timestamp &now, WritablePacket* &p);
int one_selected(const Timestamp &now, WritablePacket* &p);
void process(Packet* p);
friend class KernelTap;
......
......@@ -212,6 +212,66 @@ CLICK_DECLS
}\
}
/**
* Equivalent to CLASSIFY_EACH_PACKET but ignore the packet if fnt returns -1
*/
#define CLASSIFY_EACH_PACKET_IGNORE(nbatches,fnt,cep_batch,on_finish)\
{\
PacketBatch* out[(nbatches)];\
bzero(out,sizeof(PacketBatch*)*(nbatches));\
PacketBatch* cep_next = ((cep_batch != NULL)? static_cast<PacketBatch*>(cep_batch->next()) : NULL );\
Packet* p = cep_batch;\
Packet* last = NULL;\
int last_o = -1;\
int passed = 0;\
for (;p != NULL;p=cep_next,cep_next=(p==0?0:static_cast<PacketBatch*>(p->next()))) {\
int o = (fnt(p));\
if (o>=(nbatches)) o = (nbatches - 1);\
if (o == last_o) {\
passed ++;\
} else {\
if (last == NULL) {\
if (o == -1) continue;\
out[o] = static_cast<PacketBatch*>(p);\
out[o]->set_count(1);\
out[o]->set_tail(p);\
} else {\
if (last_o != -1) {\
out[last_o]->set_tail(last);\
out[last_o]->set_count(out[last_o]->count() + passed);\
}\
if (o != -1) {\
if (!out[o]) {\
out[o] = static_cast<PacketBatch*>(p);\
out[o]->set_count(1);\
out[o]->set_tail(p);\
} else {\
out[o]->append_packet(p);\
}\
}\
passed = 0;\
}\
}\
last = p;\
last_o = o;\
}\
\
if (passed && last_o != -1) {\
out[last_o]->set_tail(last);\
out[last_o]->set_count(out[last_o]->count() + passed);\
}\
\
int i = 0;\
for (; i < (nbatches); i++) {\
if (out[i]) {\
out[i]->tail()->set_next(NULL);\
(on_finish(i,out[i]));\
}\
}\
}
/**
* Create a batch by calling multiple times (up to max) a given function and
* linking them together in respect to the PacketBatch semantic.
......