📄 aggregateipflows.cc
字号:
{ if (_gc_sec) { reap_map(_tcp_map, _tcp_timeout, _tcp_done_timeout); reap_map(_udp_map, _udp_timeout, _udp_timeout); } _gc_sec = _active_sec + _gc_interval;}const click_ip *AggregateIPFlows::icmp_encapsulated_header(const Packet *p){ const click_icmp *icmph = p->icmp_header(); if (p->has_transport_header() && (icmph->icmp_type == ICMP_UNREACH || icmph->icmp_type == ICMP_TIMXCEED || icmph->icmp_type == ICMP_PARAMPROB || icmph->icmp_type == ICMP_SOURCEQUENCH || icmph->icmp_type == ICMP_REDIRECT)) { const click_ip *embedded_iph = reinterpret_cast<const click_ip *>(icmph + 1); unsigned embedded_hlen = embedded_iph->ip_hl << 2; if ((unsigned)p->transport_length() >= sizeof(click_icmp) + embedded_hlen && embedded_hlen >= sizeof(click_ip)) return embedded_iph; } return 0;}intAggregateIPFlows::relevant_timeout(const FlowInfo *f, const Map &m) const{ if (&m == &_udp_map) return _udp_timeout; else if (f->_flow_over == 3) return _tcp_done_timeout; else return _tcp_timeout;}// XXX timing when fragments are merged back in?AggregateIPFlows::FlowInfo *AggregateIPFlows::find_flow_info(Map &m, HostPairInfo *hpinfo, uint32_t ports, bool flipped, const Packet *p){ FlowInfo **pprev = &hpinfo->_flows; for (FlowInfo *finfo = *pprev; finfo; pprev = &finfo->_next, finfo = finfo->_next) if (finfo->_ports == ports) { // if this flow is actually dead (but has not yet been garbage // collected), then kill it for consistent semantics int age = p->timestamp_anno().sec() - finfo->_last_timestamp.sec(); // 4.Feb.2004 - Also start a new flow if the old flow closed off, // and we have a SYN. if ((age > _smallest_timeout && age > relevant_timeout(finfo, m)) || (finfo->_flow_over == 3 && p->ip_header()->ip_p == IP_PROTO_TCP && (p->tcp_header()->th_flags & TH_SYN))) { // old aggregate has died notify(finfo->aggregate(), AggregateListener::DELETE_AGG, 0); const click_ip *iph = good_ip_header(p); HostPair hp(iph->ip_src.s_addr, iph->ip_dst.s_addr); delete_flowinfo(hp, finfo, false); // make a new aggregate finfo->_aggregate = _next; _next++; finfo->_reverse = flipped; finfo->_flow_over = 0;#if CLICK_USERLEVEL if (stats()) stat_new_flow_hook(p, finfo);#endif notify(finfo->aggregate(), AggregateListener::NEW_AGG, p); } // otherwise, move to the front of the list and return *pprev = finfo->_next; finfo->_next = hpinfo->_flows; hpinfo->_flows = finfo; return finfo; } // make and install new FlowInfo pair FlowInfo *finfo;#if CLICK_USERLEVEL if (stats()) { finfo = new StatFlowInfo(ports, hpinfo->_flows, _next); stat_new_flow_hook(p, finfo); } else#endif finfo = new FlowInfo(ports, hpinfo->_flows, _next); finfo->_reverse = flipped; hpinfo->_flows = finfo; _next++; notify(finfo->aggregate(), AggregateListener::NEW_AGG, p); return finfo;}voidAggregateIPFlows::emit_fragment_head(HostPairInfo *hpinfo){ Packet *head = hpinfo->_fragment_head; hpinfo->_fragment_head = head->next(); const click_ip *iph = good_ip_header(head); // XXX multiple linear traversals of entire fragment list! // want a faster method that takes up little memory? if (AGGREGATE_ANNO(head)) { for (Packet *p = hpinfo->_fragment_head; p; p = p->next()) if (good_ip_header(p)->ip_id == iph->ip_id) { SET_AGGREGATE_ANNO(p, AGGREGATE_ANNO(head)); SET_PAINT_ANNO(p, PAINT_ANNO(head)); } } else { for (Packet *p = hpinfo->_fragment_head; p; p = p->next()) if (good_ip_header(p)->ip_id == iph->ip_id && AGGREGATE_ANNO(p)) { SET_AGGREGATE_ANNO(head, AGGREGATE_ANNO(p)); SET_PAINT_ANNO(head, PAINT_ANNO(p)); goto find_flowinfo; } head->kill(); return; } find_flowinfo: // find the packet's FlowInfo FlowInfo *finfo, **pprev = &hpinfo->_flows; for (finfo = *pprev; finfo; pprev = &finfo->_next, finfo = *pprev) if (finfo->_aggregate == AGGREGATE_ANNO(head)) { *pprev = finfo->_next; finfo->_next = hpinfo->_flows; hpinfo->_flows = finfo; break; } assert(finfo); packet_emit_hook(head, iph, finfo); output(0).push(head);}intAggregateIPFlows::handle_fragment(Packet *p, HostPairInfo *hpinfo){ if (hpinfo->_fragment_head) hpinfo->_fragment_tail->set_next(p); else hpinfo->_fragment_head = p; hpinfo->_fragment_tail = p; p->set_next(0); _active_sec = p->timestamp_anno().sec(); // get rid of old fragments int frag_timeout = _active_sec - _fragment_timeout; Packet *head; while ((head = hpinfo->_fragment_head) && (head->timestamp_anno().sec() < frag_timeout || !IP_ISFRAG(good_ip_header(head)))) emit_fragment_head(hpinfo); return ACT_NONE;}intAggregateIPFlows::handle_packet(Packet *p){ const click_ip *iph = p->ip_header(); int paint = 0; // assign timestamp if no timestamp given if (!p->timestamp_anno()) { if (!_timestamp_warning) { click_chatter("%{element}: warning: packet received without timestamp", this); _timestamp_warning = true; } p->timestamp_anno().set_now(); } // extract encapsulated ICMP header if appropriate if (p->has_network_header() && iph->ip_p == IP_PROTO_ICMP && IP_FIRSTFRAG(iph) && _handle_icmp_errors) { iph = icmp_encapsulated_header(p); paint = 2; } // return if not a proper TCP/UDP packet if (!p->has_network_header() || (iph->ip_p != IP_PROTO_TCP && iph->ip_p != IP_PROTO_UDP) || (iph->ip_src.s_addr == 0 && iph->ip_dst.s_addr == 0)) return ACT_DROP; // find relevant HostPairInfo Map &m = (iph->ip_p == IP_PROTO_TCP ? _tcp_map : _udp_map); HostPair hosts(iph->ip_src.s_addr, iph->ip_dst.s_addr); if (hosts.a != iph->ip_src.s_addr) paint ^= 1; HostPairInfo *hpinfo = &m[hosts]; // find relevant FlowInfo, if any FlowInfo *finfo; if (IP_FIRSTFRAG(iph)) { const uint8_t *udp_ptr = reinterpret_cast<const uint8_t *>(iph) + (iph->ip_hl << 2); if (udp_ptr + 4 > p->end_data()) // packet not big enough return ACT_DROP; uint32_t ports = *reinterpret_cast<const uint32_t *>(udp_ptr); // 1.Jan.08: handle connections where IP addresses are the same (John // Russell Lane) if (hosts.a == hosts.b && ports_reverse_order(ports)) paint ^= 1; if (paint & 1) ports = flip_ports(ports); finfo = find_flow_info(m, hpinfo, ports, paint & 1, p); if (!finfo) { click_chatter("out of memory!"); return ACT_DROP; } if (finfo->reverse()) paint ^= 1; // set aggregate annotations SET_AGGREGATE_ANNO(p, finfo->aggregate()); SET_PAINT_ANNO(p, paint); } else { finfo = 0; SET_AGGREGATE_ANNO(p, 0); SET_PAINT_ANNO(p, paint); } // check for fragment if ((_fragments && IP_ISFRAG(iph)) || hpinfo->_fragment_head) return handle_fragment(p, hpinfo); else if (!finfo) return ACT_DROP; // packet emit hook _active_sec = p->timestamp_anno().sec(); packet_emit_hook(p, iph, finfo); return ACT_EMIT;}voidAggregateIPFlows::push(int, Packet *p){ int action = handle_packet(p); // GC if necessary if (_active_sec >= _gc_sec) reap(); if (action == ACT_EMIT) output(0).push(p); else if (action == ACT_DROP) checked_output_push(1, p);}Packet *AggregateIPFlows::pull(int){ Packet *p = input(0).pull(); int action = (p ? handle_packet(p) : ACT_NONE); // GC if necessary if (_active_sec >= _gc_sec) reap(); if (action == ACT_EMIT) return p; else if (action == ACT_DROP) checked_output_push(1, p); return 0;}enum { H_CLEAR };intAggregateIPFlows::write_handler(const String &, Element *e, void *thunk, ErrorHandler *){ AggregateIPFlows *af = static_cast<AggregateIPFlows *>(e); switch ((intptr_t)thunk) { case H_CLEAR: { int active_sec = af->_active_sec, gc_sec = af->_gc_sec; af->_active_sec = af->_gc_sec = 0x7FFFFFFF; af->reap(); af->_active_sec = active_sec, af->_gc_sec = gc_sec; return 0; } default: return -1; }}voidAggregateIPFlows::add_handlers(){ add_write_handler("clear", write_handler, (void *)H_CLEAR);}ELEMENT_REQUIRES(AggregateNotifier)EXPORT_ELEMENT(AggregateIPFlows)CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -