📄 fromipsumdump.cc
字号:
if (_binary) { Vector<const unsigned char *> args; int nbytes; for (const IPSummaryDump::FieldReader * const *fp = _fields.begin(); fp != _fields.end(); ++fp) { if (!(*fp)->inb) goto bad_field; switch ((*fp)->type) { case IPSummaryDump::B_0: nbytes = 0; goto got_nbytes; case IPSummaryDump::B_1: nbytes = 1; goto got_nbytes; case IPSummaryDump::B_2: nbytes = 2; goto got_nbytes; case IPSummaryDump::B_4: case IPSummaryDump::B_4NET: nbytes = 4; goto got_nbytes; case IPSummaryDump::B_6PTR: nbytes = 6; goto got_nbytes; case IPSummaryDump::B_8: nbytes = 8; goto got_nbytes; case IPSummaryDump::B_16: nbytes = 16; goto got_nbytes; got_nbytes: if (data + nbytes <= end) { args.push_back((const unsigned char *) data); data += nbytes; } else goto bad_field; break; case IPSummaryDump::B_SPECIAL: args.push_back((const unsigned char *) data); data = (const char *) (*fp)->inb(d, (const uint8_t *) data, (const uint8_t *) end, *fp); break; bad_field: default: args.push_back(0); data = end; break; } } for (int *fip = _field_order.begin(); fip != _field_order.end() && d.p; ++fip) { const IPSummaryDump::FieldReader *f = _fields[*fip]; if (!args[*fip] || !f->inject) continue; d.clear_values(); if (f->inb(d, args[*fip], (const uint8_t *) end, f)) { f->inject(d, f); nfields++; } } } else { Vector<String> args; while (args.size() < _fields.size()) { const char *original_data = data; while (data < end) if (isspace((unsigned char) *data)) break; else if (*data == '\"') data = cp_skip_double_quote(data, end); else ++data; args.push_back(line.substring(original_data, data)); while (data < end && isspace((unsigned char) *data)) ++data; } for (int *fip = _field_order.begin(); fip != _field_order.end() && d.p; ++fip) { const IPSummaryDump::FieldReader *f = _fields[*fip]; if (!args[*fip] || args[*fip].equals("-", 1) || !f->inject) continue; d.clear_values(); if (f->ina(d, args[*fip], f)) { f->inject(d, f); nfields++; } } } if (!nfields) { // bad format if (!_format_complaint) { // don't complain if the line was all blank if (binary || !cp_is_space(line)) { if (_fields.size() == 0) _ff.error(errh, "no '!data' provided"); else _ff.error(errh, "packet parse error"); _format_complaint = true; } } if (d.p) d.p->kill(); d.p = 0; } // set source and destination ports even if no transport info on packet if (d.p && d.default_ip_flowid) (void) d.make_ip(0); // may fail // set up transport header if necessary if (d.p && d.is_ip && d.p->ip_header()) (void) d.make_transp(); if (d.p && d.is_ip && d.p->ip_header()) { // set IP length uint32_t ip_len; if (!d.p->ip_header()->ip_len) { ip_len = d.want_len; if (ip_len >= (uint32_t) d.p->network_header_offset()) ip_len -= d.p->network_header_offset(); if (ip_len > 0xFFFF) ip_len = 0xFFFF; else if (ip_len == 0) ip_len = d.p->network_length(); d.p->ip_header()->ip_len = htons(ip_len); } else ip_len = ntohs(d.p->ip_header()->ip_len); // set UDP length if (d.p->ip_header()->ip_p == IP_PROTO_UDP && IP_FIRSTFRAG(d.p->ip_header()) && !d.p->udp_header()->uh_ulen) { int len = ip_len - d.p->network_header_length(); d.p->udp_header()->uh_ulen = htons(len); } // set destination IP address annotation d.p->set_dst_ip_anno(d.p->ip_header()->ip_dst); // set checksum if (_checksum) { uint32_t xlen = 0; if (ip_len > (uint32_t) d.p->network_length()) xlen = ip_len - d.p->network_length(); if (!xlen || (d.p = d.p->put(xlen))) { if (xlen && _zero) memset(d.p->end_data() - xlen, 0, xlen); SET_EXTRA_LENGTH_ANNO(d.p, EXTRA_LENGTH_ANNO(d.p) - xlen); set_checksums(d.p, d.p->ip_header()); } } } // set extra length annotation (post-other length adjustments) if (d.p && d.want_len > d.p->length()) SET_EXTRA_LENGTH_ANNO(d.p, d.want_len - d.p->length()); return d.p;}inline Packet *set_packet_lengths(Packet *p, uint32_t extra_length){ uint32_t length = p->length() + extra_length; if (htons(length) != p->ip_header()->ip_len) { if (WritablePacket *q = p->uniqueify()) { click_ip *ip = q->ip_header(); ip->ip_len = htons(length); if (ip->ip_p == IP_PROTO_UDP) q->udp_header()->uh_ulen = htons(length - (ip->ip_hl << 2)); return q; } else return 0; } else return p;}Packet *FromIPSummaryDump::handle_multipacket(Packet *p){ assert(!_work_packet || _work_packet == p); if (!p || !EXTRA_PACKETS_ANNO(p)) { _work_packet = 0; return p; } uint32_t count = 1 + EXTRA_PACKETS_ANNO(p); // set up _multipacket variables on new packets (_work_packet == 0) if (!_work_packet) { assert(count > 1); // set length of all but the last packet _multipacket_length = (p->length() + EXTRA_LENGTH_ANNO(p)) / count; // beware if there isn't enough EXTRA_LENGTH to cover all the packets if (_multipacket_length < p->length()) { _multipacket_length = p->length(); SET_EXTRA_LENGTH_ANNO(p, _multipacket_length * (count - 1)); } // set timestamps _multipacket_end_timestamp = p->timestamp_anno(); if (FIRST_TIMESTAMP_ANNO(p)) { _multipacket_timestamp_delta = (p->timestamp_anno() - FIRST_TIMESTAMP_ANNO(p)) / (count - 1); p->timestamp_anno() = FIRST_TIMESTAMP_ANNO(p); } else _multipacket_timestamp_delta = Timestamp(); // prepare IP lengths for _multipacket_extra_length _work_packet = set_packet_lengths(p, _multipacket_length - p->length()); if (!_work_packet) return 0; } // prepare packet to return if ((p = p->clone())) { SET_EXTRA_PACKETS_ANNO(p, 0); SET_EXTRA_LENGTH_ANNO(p, _multipacket_length - p->length()); } // reduce weight of _work_packet SET_EXTRA_PACKETS_ANNO(_work_packet, count - 2); SET_EXTRA_LENGTH_ANNO(_work_packet, EXTRA_LENGTH_ANNO(_work_packet) - _multipacket_length); if (count == 2) { _work_packet->timestamp_anno() = _multipacket_end_timestamp; _work_packet = set_packet_lengths(_work_packet, EXTRA_LENGTH_ANNO(_work_packet)); } else _work_packet->timestamp_anno() += _multipacket_timestamp_delta; return p;}voidFromIPSummaryDump::run_timer(Timer *){ if (_active) { if (output_is_pull(0)) _notifier.wake(); else _task.reschedule(); }}boolFromIPSummaryDump::check_timing(Packet *p){ assert(!_work_packet || _work_packet == p); if (!_have_timing) { _timing_offset = Timestamp::now() - p->timestamp_anno(); _have_timing = true; } Timestamp now = Timestamp::now(); Timestamp t = p->timestamp_anno() + _timing_offset; if (now < t) { t -= Timer::adjustment(); if (now < t) { _timer.schedule_at(t); if (output_is_pull(0)) _notifier.sleep(); } else { if (output_is_push(0)) _task.fast_reschedule(); } _work_packet = p; return false; } _work_packet = 0; return true;}boolFromIPSummaryDump::run_task(Task *){ if (!_active) return false; Packet *p; while (1) { p = (_work_packet ? _work_packet : read_packet(0)); if (!p && !_ff.initialized()) { if (_stop) router()->please_stop_driver(); return false; } else if (!p) break; if (p && _timing && !check_timing(p)) return false; if (_multipacket) p = handle_multipacket(p); // check sampling probability if (_sampling_prob >= (1 << SAMPLING_SHIFT) || (click_random() & ((1 << SAMPLING_SHIFT) - 1)) < _sampling_prob) break; if (p) p->kill(); } if (p) output(0).push(p); _task.fast_reschedule(); return true;}Packet *FromIPSummaryDump::pull(int){ if (!_active) return 0; Packet *p; while (1) { p = (_work_packet ? _work_packet : read_packet(0)); if (!p && !_ff.initialized()) { if (_stop) router()->please_stop_driver(); _notifier.sleep(); return 0; } if (p && _timing && !check_timing(p)) return 0; if (_multipacket) p = handle_multipacket(p); // check sampling probability if (_sampling_prob >= (1 << SAMPLING_SHIFT) || (click_random() & ((1 << SAMPLING_SHIFT) - 1)) < _sampling_prob) break; if (p) p->kill(); } _notifier.wake(); return p;}enum { H_SAMPLING_PROB, H_ACTIVE, H_ENCAP, H_STOP };StringFromIPSummaryDump::read_handler(Element *e, void *thunk){ FromIPSummaryDump *fd = static_cast<FromIPSummaryDump *>(e); switch ((intptr_t)thunk) { case H_SAMPLING_PROB: return cp_unparse_real2(fd->_sampling_prob, SAMPLING_SHIFT); case H_ACTIVE: return cp_unparse_bool(fd->_active); case H_ENCAP: return "IP"; default: return "<error>"; }}intFromIPSummaryDump::write_handler(const String &s_in, Element *e, void *thunk, ErrorHandler *errh){ FromIPSummaryDump *fd = static_cast<FromIPSummaryDump *>(e); String s = cp_uncomment(s_in); switch ((intptr_t)thunk) { case H_ACTIVE: { bool active; if (cp_bool(s, &active)) { fd->_active = active; if (fd->output_is_push(0) && active && !fd->_task.scheduled()) fd->_task.reschedule(); else if (!fd->output_is_push(0)) fd->_notifier.set_active(active, true); return 0; } else return errh->error("'active' should be Boolean"); } case H_STOP: fd->_active = false; fd->router()->please_stop_driver(); return 0; default: return -EINVAL; }}voidFromIPSummaryDump::add_handlers(){ add_read_handler("sampling_prob", read_handler, H_SAMPLING_PROB); add_read_handler("active", read_handler, H_ACTIVE, Handler::CHECKBOX); add_write_handler("active", write_handler, H_ACTIVE); add_read_handler("encap", read_handler, H_ENCAP); add_write_handler("stop", write_handler, H_STOP, Handler::BUTTON); _ff.add_handlers(this); if (output_is_push(0)) add_task_handlers(&_task);}ELEMENT_REQUIRES(userlevel FromFile IPSummaryDumpInfo)EXPORT_ELEMENT(FromIPSummaryDump)CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -