📄 aggregateip.cc
字号:
/* * aggregateip.{cc,hh} -- set aggregate annotation based on IP field * Eddie Kohler * * Copyright (c) 2001-2003 International Computer Science Institute * Copyright (c) 2005 Regents of the University of California * * 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 "aggregateip.hh"#include <click/error.hh>#include <click/hashmap.hh>#include <click/straccum.hh>#include <click/confparse.hh>#include <clicknet/ip.h>#include <clicknet/tcp.h>#include <clicknet/udp.h>#include <click/packet_anno.hh>CLICK_DECLSAggregateIP::AggregateIP() : Element(1, 1){}AggregateIP::~AggregateIP(){}voidAggregateIP::notify_noutputs(int n){ set_noutputs(n <= 1 ? 1 : 2);}intAggregateIP::configure(Vector<String> &conf, ErrorHandler *errh){ String arg; _incremental = _unshift_ip_addr = false; if (cp_va_parse(conf, this, errh, cpArgument, "field specification", &arg, cpKeywords, "INCREMENTAL", cpBool, "incremental?", &_incremental, "UNSHIFT_IP_ADDR", cpBool, "unshift IP address fields?", &_unshift_ip_addr, cpEnd) < 0) return -1; const char *end = IPField::parse(arg.begin(), arg.end(), -1, &_f, errh, this); if (end == arg.begin()) return -1; else if (end != arg.end()) return errh->error("garbage after field specification"); int32_t right = _f.bit_offset() + _f.bit_length() - 1; if ((_f.bit_offset() / 32) != (right / 32)) return errh->error("field specification does not fit within a single word"); if (_f.bit_length() > 32) return errh->error("too many aggregates: field length too large, max 32"); else if (_f.bit_length() == 32 && _incremental) return errh->error("`INCREMENTAL' is incompatible with field length 32"); if (_f.bit_length() == 32) _mask = 0xFFFFFFFFU; else _mask = (1 << _f.bit_length()) - 1; _offset = (_f.bit_offset() / 32) * 4; if (!_unshift_ip_addr || _f.proto() != 0 || _f.bit_offset() < 12*8 || _f.bit_offset() >= 20*8) _shift = 31 - right % 32; else { _mask <<= 31 - right % 32; _shift = 0; } return 0;}Packet *AggregateIP::bad_packet(Packet *p){ if (noutputs() == 2) output(1).push(p); else p->kill(); return 0;}Packet *AggregateIP::handle_packet(Packet *p){ const click_ip *iph = p->ip_header(); if (!iph) return bad_packet(p); int offset = p->length(); switch (_f.proto()) { case 0: offset = p->network_header_offset(); break; case IP_PROTO_TCP_OR_UDP: if (IP_FIRSTFRAG(iph) && (iph->ip_p == IP_PROTO_TCP || iph->ip_p == IP_PROTO_UDP)) offset = p->transport_header_offset(); break; case IP_PROTO_TRANSP: if (IP_FIRSTFRAG(iph)) offset = p->transport_header_offset(); break; case IP_PROTO_PAYLOAD: if (!IP_FIRSTFRAG(iph)) /* bad; will be thrown away below */; else if (iph->ip_p == IPPROTO_TCP && p->transport_header_offset() + sizeof(click_tcp) <= p->length()) { const click_tcp *tcph = (const click_tcp *)p->transport_header(); offset = p->transport_header_offset() + (tcph->th_off << 2); } else if (iph->ip_p == IPPROTO_UDP) offset = p->transport_header_offset() + sizeof(click_udp); break; default: if (IP_FIRSTFRAG(iph) && iph->ip_p == _f.proto()) offset = p->transport_header_offset(); break; } offset += _offset; if (offset + 4 > (int)p->length()) return bad_packet(p); uint32_t udata = *((const uint32_t *)(p->data() + offset)); uint32_t agg = (ntohl(udata) >> _shift) & _mask; if (_incremental) SET_AGGREGATE_ANNO(p, AGGREGATE_ANNO(p)*(_mask + 1) + agg); else SET_AGGREGATE_ANNO(p, agg); return p;}voidAggregateIP::push(int, Packet *p){ if (Packet *q = handle_packet(p)) output(0).push(q);}Packet *AggregateIP::pull(int){ Packet *p = input(0).pull(); if (p) p = handle_packet(p); return p;}StringAggregateIP::read_handler(Element *e, void *thunk){ AggregateIP *aip = static_cast<AggregateIP *>(e); switch ((intptr_t)thunk) { case 0: return NameInfo::revquery_int(NameInfo::T_IP_PROTO, e, aip->_f.proto()); case 1: return String(aip->_f.bit_offset()) + "\n"; case 2: return String(aip->_f.bit_length()) + "\n"; case 3: return aip->_f.unparse(e, false) + "\n"; default: return "<error>\n"; }}voidAggregateIP::add_handlers(){ add_read_handler("header", read_handler, (void *)0); add_read_handler("bit_offset", read_handler, (void *)1); add_read_handler("bit_length", read_handler, (void *)2); add_read_handler("field", read_handler, (void *)3);}ELEMENT_REQUIRES(userlevel IPFieldInfo)EXPORT_ELEMENT(AggregateIP)#include <click/vector.cc>CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -