diff --git a/elements/ip6/setip6ecn.cc b/elements/ip6/setip6ecn.cc new file mode 100644 index 0000000000..03edfcbdd8 --- /dev/null +++ b/elements/ip6/setip6ecn.cc @@ -0,0 +1,81 @@ +/* + * setip6ecn.{cc,hh} -- element sets IP6 header ECN field + * Glenn Minne + * + * Copyright (c) 2009 Intel Corporation + * + * 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 +#include "setip6ecn.hh" +#include +#include +#include +CLICK_DECLS + +SetIP6ECN::SetIP6ECN() +{ +} + +SetIP6ECN::~SetIP6ECN() +{ +} + +int +SetIP6ECN::configure(Vector &conf, ErrorHandler *errh) +{ + String ecn; + if (Args(conf, this, errh).read_mp("ECN", AnyArg(), ecn).complete() < 0) + return -1; + if (ecn.length() == 1 && ecn[0] >= '0' && ecn[0] <= '3') + _ecn = ecn[0] - '0'; // subtract zero ASCII character since we are working with integers, not with chars + else if (ecn.equals("no", 2) || ecn.equals("-", 1)) + _ecn = 0; + else if (ecn.equals("ect1", 4) || ecn.equals("ECT(1)", 6)) + _ecn = 1; + else if (ecn.equals("ect2", 4) || ecn.equals("ECT(0)", 6)) + _ecn = 2; + else if (ecn.equals("ce", 2) || ecn.equals("CE", 2)) + _ecn = 3; + else + return errh->error("bad ECN argument"); + return 0; +} + +Packet * +SetIP6ECN::simple_action(Packet *p) +{ + assert(p->has_network_header()); + WritablePacket *q; + if (!(q = p->uniqueify())) + return 0; + click_ip6 *ip6 = q->ip6_header(); + // This first sets the original ECN bits to 00 with & 0b11111111110011111111111111111111, after which the two new ECN bits + // are set with an OR operation. Our two bits are internally saved as 00000000000000000000000000000xx with our x's + // always being '1' or '0'. + // Because they need to come on position 11 and 12 of our ip6_flow and not on position 31 or 32, they need to be shifted 20 places + // to the left first to get them where they finally need to be in ip6_flow of our IPv6 packet, before we can OR. + ip6->ip6_flow = ((ip6->ip6_flow & htonl(0b11111111110011111111111111111111)) | htonl(_ecn << 20)); + + return q; +} + +void +SetIP6ECN::add_handlers() +{ + add_read_handler("ecn", read_keyword_handler, "0 ECN", Handler::CALM); + add_write_handler("ecn", reconfigure_keyword_handler, "0 ECN"); +} + +CLICK_ENDDECLS +EXPORT_ELEMENT(SetIP6ECN) +ELEMENT_MT_SAFE(SetIP6ECN) diff --git a/elements/ip6/setip6ecn.hh b/elements/ip6/setip6ecn.hh new file mode 100644 index 0000000000..737d19680e --- /dev/null +++ b/elements/ip6/setip6ecn.hh @@ -0,0 +1,42 @@ +#ifndef CLICK_SETIP6ECN_HH +#define CLICK_SETIP6ECN_HH +#include +CLICK_DECLS + +/* + * =c + * SetIP6ECN(ECN) + * =s ip6 + * sets IPv6 packets' ECN fields + * =d + * Expects IPv6 packets as input and + * sets their ECN bits to ECN. + * This value is either a number from 0 to 3 or a keyword, namely "no", + * "ect1"/"ECT(1)", "ect2"/"ECT(0)", or "ce"/"CE". + * Then it passes the packet to output 0. + * The ECN bits are the 2 least-significant bits in the Traffic Class field. + * =sa SetIPDSCP, MarkIPCE + */ + +class SetIP6ECN : public Element { public: + + SetIP6ECN() CLICK_COLD; + ~SetIP6ECN() CLICK_COLD; + + const char *class_name() const { return "SetIP6ECN"; } + const char *port_count() const { return PORTS_1_1; } + + int configure(Vector &, ErrorHandler *) CLICK_COLD; + bool can_live_reconfigure() const { return true; } + void add_handlers() CLICK_COLD; + + Packet *simple_action(Packet *); + + private: + + uint32_t _ecn; + +}; + +CLICK_ENDDECLS +#endif diff --git a/elements/ip6/setip6flowlabel.cc b/elements/ip6/setip6flowlabel.cc new file mode 100644 index 0000000000..013e976826 --- /dev/null +++ b/elements/ip6/setip6flowlabel.cc @@ -0,0 +1,82 @@ +/* + * setip6flowlabel.{cc,hh} -- element sets IP6 flow label field + * Glenn Minne + * + * Copyright (c) 2002 Massachusetts Institute of Technology + * + * 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 +#include "setip6flowlabel.hh" +#include +#include +#include +CLICK_DECLS + +SetIP6FlowLabel::SetIP6FlowLabel() +{ +} + +SetIP6FlowLabel::~SetIP6FlowLabel() +{ +} + +int +SetIP6FlowLabel::configure(Vector &conf, ErrorHandler *errh) +{ + if (Args(conf, this, errh).read_mp("FLOW", _flow_label).complete() < 0) + return -1; + if (_flow_label > 1048575) + return errh->error("flow label out of range"); + + return 0; +} + + +inline Packet * +SetIP6FlowLabel::smaction(Packet *p_in) +{ + WritablePacket *p = p_in->uniqueify(); + assert(p->has_network_header()); + click_ip6 *ip6 = p->ip6_header(); + + ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = ((htonl(0b11111111111100000000000000000000) & ip6->ip6_ctlun.ip6_un1.ip6_un1_flow) | htonl(_flow_label)); + + return p; +} + +void +SetIP6FlowLabel::push(int, Packet *p) +{ + if ((p = smaction(p)) != 0) + output(0).push(p); +} + +Packet * +SetIP6FlowLabel::pull(int) +{ + Packet *p = input(0).pull(); + if (p) + p = smaction(p); + return p; +} + +void +SetIP6FlowLabel::add_handlers() +{ + add_read_handler("flowlabel", read_keyword_handler, "0 FlowLabel", Handler::CALM); + add_write_handler("flowlabel", reconfigure_keyword_handler, "0 FlowLabel"); +} + +CLICK_ENDDECLS +EXPORT_ELEMENT(SetIP6FlowLabel) +ELEMENT_MT_SAFE(SetIP6FlowLabel) diff --git a/elements/ip6/setip6flowlabel.hh b/elements/ip6/setip6flowlabel.hh new file mode 100644 index 0000000000..db94bb7658 --- /dev/null +++ b/elements/ip6/setip6flowlabel.hh @@ -0,0 +1,45 @@ +#ifndef CLICK_SETIP6FLOWLABEL_HH +#define CLICK_SETIP6FLOWLABEL_HH + +/* + * =c + * SetIP6FlowLabel(VAL) + * =s ip6 + * sets IP6 packets' Flow Label field + * =d + * Expects IP6 packets as input and + * sets their Flow Label to VAL + * and passes the packet to output 0. + */ + +#include +#include +#include +CLICK_DECLS + +class SetIP6FlowLabel : public Element { public: + + SetIP6FlowLabel(); + ~SetIP6FlowLabel(); + + const char *class_name() const { return "SetIP6FlowLabel"; } + const char *port_count() const { return PORTS_1_1; } + + int configure(Vector &conf, ErrorHandler *errh) CLICK_COLD; + bool can_live_reconfigure() const { return true; } + void add_handlers() CLICK_COLD; + + inline Packet *smaction(Packet *p); + void push(int port, Packet *p); + Packet *pull(int port); + + private: + + uint32_t _flow_label;/* is only 20 bits long but we cannot represent a 20-bit type */ + /* however, we prevent from assigning this a value longer than 20-bits, */ + /* if it still happens, we return an error */ + +}; + +CLICK_ENDDECLS +#endif diff --git a/elements/ip6/setip6hlim.cc b/elements/ip6/setip6hlim.cc new file mode 100644 index 0000000000..91e4c904b3 --- /dev/null +++ b/elements/ip6/setip6hlim.cc @@ -0,0 +1,80 @@ +/* + * setip6hlim.{cc,hh} -- element sets IP6 hop limit field + * Glenn Minne + * + * Copyright (c) 2002 Massachusetts Institute of Technology + * + * 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 +#include "setip6hlim.hh" +#include +#include +#include +CLICK_DECLS + +SetIP6Hlim::SetIP6Hlim() +{ +} + +SetIP6Hlim::~SetIP6Hlim() +{ +} + +int +SetIP6Hlim::configure(Vector &conf, ErrorHandler *errh) +{ + if (Args(conf, this, errh).read_mp("HLIM", _hlim).complete() < 0) + return -1; + + return 0; +} + + +inline Packet * +SetIP6Hlim::smaction(Packet *p_in) +{ + WritablePacket *p = p_in->uniqueify(); + assert(p->has_network_header()); + click_ip6 *ip6 = p->ip6_header(); + + ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = _hlim; + + return p; +} + +void +SetIP6Hlim::push(int, Packet *p) +{ + if ((p = smaction(p)) != 0) + output(0).push(p); +} + +Packet * +SetIP6Hlim::pull(int) +{ + Packet *p = input(0).pull(); + if (p) + p = smaction(p); + return p; +} + +void +SetIP6Hlim::add_handlers() +{ + add_read_handler("hopLimit", read_keyword_handler, "0 SetIP6Hlim", Handler::CALM); + add_write_handler("hopLimit", reconfigure_keyword_handler, "0 SetIP6Hlim"); +} + +CLICK_ENDDECLS +EXPORT_ELEMENT(SetIP6Hlim) +ELEMENT_MT_SAFE(SetIP6Hlim) diff --git a/elements/ip6/setip6hlim.hh b/elements/ip6/setip6hlim.hh new file mode 100644 index 0000000000..d57419efca --- /dev/null +++ b/elements/ip6/setip6hlim.hh @@ -0,0 +1,41 @@ +#ifndef CLICK_SETIP6HLIM_HH +#define CLICK_SETIP6HLIM_HH + +/* + * =c + * SetIP6HLim(VAL) + * =s ip6 + * sets IP6 packets' Hop Limit field + * =d + * Expects IP6 packets as input and + * sets their Hop Limit to VAL + * and passes the packet to output 0. + */ + +#include +#include +#include +CLICK_DECLS + +class SetIP6Hlim : public Element { public: + SetIP6Hlim(); + ~SetIP6Hlim(); + + const char *class_name() const { return "SetIP6Hlim"; } + const char *port_count() const { return PORTS_1_1; } + + int configure(Vector &conf, ErrorHandler *errh) CLICK_COLD; + bool can_live_reconfigure() const { return true; } + void add_handlers() CLICK_COLD; + + inline Packet *smaction(Packet *p); + void push(int port, Packet *p); + Packet *pull(int port); + + private: + uint8_t _hlim; /* field containing the hop limit */ + +}; + +CLICK_ENDDECLS +#endif /* CLICK_SETIP6HLIM_HH */ diff --git a/elements/ip6/storeip6address.cc b/elements/ip6/storeip6address.cc new file mode 100644 index 0000000000..cad7ab6489 --- /dev/null +++ b/elements/ip6/storeip6address.cc @@ -0,0 +1,87 @@ +/* + * storeip6address.{cc,hh} -- element stores IPv6 destination annotation into + * packet + * Glenn Minne + * + * 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. + * + * For using the 'src' and 'dst argument the IPv6 header pointers MUST be set. + */ + +#include +#include "storeip6address.hh" +#include +#include +#include +#include +#include +CLICK_DECLS + +StoreIP6Address::StoreIP6Address() +{ +} + +StoreIP6Address::~StoreIP6Address() +{ +} + +int +StoreIP6Address::configure(Vector &conf, ErrorHandler *errh) +{ + + String offset; // the offset to be read; can be equal to src or dst in stead of a number, in which case this has a special meaning. + int r; // reply + + if (conf.size() == 1) { + r = Args(conf, this, errh).read_mp("OFFSET", WordArg(), offset).complete(); + _address_given = false; + } else if (conf.size() == 2) { + r = Args(conf, this, errh).read_mp("ADDR", _address).read_mp("OFFSET", WordArg(), offset).complete(); + _address_given = true; + } else { // conf size should be 1 or 2 + return -1; + } + + if (r < 0) { // a parse error occured, we should stop and return an error. + return r; + } + + /* translate src and dst into their actual number counterparts */ + if (offset.lower() == "src") { + _offset = 8; + } else if (offset.lower() == "dst") { + _offset = 24; + } else { // normal parsing needs to be done + bool parseErrors = IntArg().parse(offset, _offset); //parse offset and place it in _offset + if (!parseErrors || _offset < 0) { + return -1; + } + } + return 0; +} + +Packet * +StoreIP6Address::simple_action(Packet *p_in) +{ + if (!_address_given) { // if no address was explicitely given, we need to read it in via p->dst_ip6_anno() + _address = DST_IP6_ANNO(p_in); + } + WritablePacket *p = p_in->uniqueify(); + assert(p->has_network_header()); + in6_addr *ip6_address_pointer = (in6_addr*) ((uint8_t*) (p->ip6_header()) + _offset); + *ip6_address_pointer = _address; + + return p; +} + +CLICK_ENDDECLS +EXPORT_ELEMENT(StoreIP6Address) +ELEMENT_MT_SAFE(StoreIP6Address) diff --git a/elements/ip6/storeip6address.hh b/elements/ip6/storeip6address.hh new file mode 100644 index 0000000000..7a71c6a887 --- /dev/null +++ b/elements/ip6/storeip6address.hh @@ -0,0 +1,68 @@ +#ifndef CLICK_STOREIP6ADDRESS_HH +#define CLICK_STOREIP6ADDRESS_HH +#include +#include +CLICK_DECLS + +/* +=c +StoreIP6Address(OFFSET) +StoreIP6Address(ADDR, OFFSET) +=s ip6 +stores IPv6 address in packet +=d + +The one-argument form writes the destination IPv6 address annotation into the +packet at offset OFFSET, usually an integer. But if the annotation is zero, it +doesn't change the packet. + +The two-argument form writes IPv6 address ADDR into the packet at offset +OFFSET. + +The OFFSET argument may also be a special thing as 'src' or 'dst' refering to respectively, +the offset of the source address and destination address in an IPv6 packet. + +=e +FromDevice(eth1) +-> Strip(14) +-> CheckIP6Header +-> ip6filter :: IP6Classifier(src host 2001:2:f000::1 and nxt 59) + +ip6filter[0] +-> DecIP6HLIM +-> Unstrip(14) +-> StoreEtherAddress(00:0a:95:9d:68:16, 'src') +-> StoreEtherAddress(00:0a:95:9d:68:17, 'dst') +-> StoreIP6Address(2001:2:f000::3, 'src') // change source address to 2001:2:f000::3 +-> StoreIP6Address(2001:2:1::4, 'dst') // change destination address to 2001:2:1::4 +-> q :: Queue +-> ToDevice(eth0) + +ip6filter[1] +-> Discard; + +=a +CheckIP6Header +*/ + +class StoreIP6Address : public Element { public: + + StoreIP6Address() CLICK_COLD; + ~StoreIP6Address() CLICK_COLD; + + const char *class_name() const { return "StoreIP6Address"; } + const char *port_count() const { return PORTS_1_1X2; } + const char *processing() const { return PROCESSING_A_AH; } + + int configure(Vector &, ErrorHandler *) CLICK_COLD; + + Packet *simple_action(Packet *); + + private: + int _offset; + IP6Address _address; + bool _address_given; +}; + +CLICK_ENDDECLS +#endif