📄 peer.cc
字号:
debug_msg("callback %s %s\n", comment, error.str().c_str()); if(XrlError::OKAY() != error) { XLOG_WARNING("callback: %s %s", comment, error.str().c_str()); fclose(fp); return; } if(packets_to_send != 0 && packet_number == packets_to_send) { fclose(fp); return; } size_t len; const uint8_t *buf; while(0 != (buf = mrtd_traffic_file_read(fp, len))) { const fixed_header *header = reinterpret_cast<const struct fixed_header *>(buf); if(MESSAGETYPEUPDATE == header->type) { /* ** Save the update message in the sent trie. */ TimeVal tv; _eventloop->current_time(tv); _trie_sent.process_update_packet(tv, buf, len); _smcb = callback(this, &Peer::send_dump_callback, fp, packet_number + 1, packets_to_send, "mrtd_traffic_send"); send_message(buf, len, _smcb); return; } else { delete [] buf; } } fclose(fp);}voidPeer::trie(const string& line, const vector<string>& words) throw(InvalidString){ if(words.size() < 4) xorp_throw(InvalidString, c_format("Insufficient arguments:\n[%s]", line.c_str())); /* ** Each peer holds two tries. One holds updates sent the other ** holds updates received. Determine which trie we are about to ** operate on. */ Trie *op; if("sent" == words[2]) { op = &_trie_sent; } else if("recv" == words[2]) { op = &_trie_recv; } else xorp_throw(InvalidString, c_format("\"sent\" or \"recv\" accepted not <%s>\n[%s]", words[2].c_str(), line.c_str())); /* ** The only operation currently supported is lookup */ if("lookup" != words[3]) xorp_throw(InvalidString, c_format("\"lookup\" expected not <%s>\n[%s]", words[3].c_str(), line.c_str())); if(words.size() < 5) xorp_throw(InvalidString, c_format("No arguments for \"lookup\"\n[%s]", line.c_str())); const UpdatePacket *bgpupdate = op->lookup(words[4]); if(0 == bgpupdate) { if((words.size() == 6) && ("not" == words[5])) return; xorp_throw(InvalidString, c_format("Lookup failed [%s]", line.c_str())); } if((words.size() == 6) && ("not" == words[5])) xorp_throw(InvalidString, c_format("Lookup failed entry exists [%s]", line.c_str())); debug_msg("Found: %s\n", bgpupdate->str().c_str()); size_t size = words.size(); if(0 == (size % 2)) xorp_throw(InvalidString, c_format("Incorrect number of arguments:\n[%s]", line.c_str())); for(size_t i = 5; i < size; i += 2) { debug_msg("attribute: %s value: %s\n", words[i].c_str(), words[i + 1].c_str()); if("aspath" == words[i]) { /* ** Search for the AS Path in the update packet. */ const list<PathAttribute*>& palist = bgpupdate->pa_list(); list<PathAttribute*>::const_iterator pai; const AsPath *aspath = 0; for(pai = palist.begin(); pai != palist.end(); pai++) { if(AS_PATH == (*pai)->type()) aspath = &((static_cast<ASPathAttribute *>(*pai))-> as_path()); } if(0 == aspath) xorp_throw(InvalidString, c_format("NO AS Path associated with route\n[%s]", line.c_str())); if(*aspath != AsPath(words[i + 1].c_str())) xorp_throw(InvalidString, c_format("Looking for Path: <%s> Found: <%s>\n[%s]", words[i + 1].c_str(), aspath->str().c_str(), line.c_str())); } else xorp_throw(InvalidString, c_format("Illegal attribute: <%s>\n[%s]", words[i].c_str(), line.c_str())); }}/*** peer expect packet ...** 0 1 2*/voidPeer::expect(const string& line, const vector<string>& words) throw(InvalidString){ if(words.size() < 3) xorp_throw(InvalidString, c_format("Insufficient arguments:\n[%s]", line.c_str())); if("packet" == words[2]) { _expect._list.push_back(packet(line, words, 3)); } else xorp_throw(InvalidString, c_format( "\"packet\" accepted not <%s>\n[%s]", words[2].c_str(), line.c_str()));}/*** peer assert queue** 0 1 2**** peer assert queue <len>** 0 1 2 3**** peer assert established** 0 1 2**** peer assert idle** 0 1 2*/voidPeer::assertX(const string& line, const vector<string>& words) throw(InvalidString){ if(words.size() < 3) xorp_throw(InvalidString, c_format("Insufficient arguments:\n[%s]", line.c_str())); if("queue" == words[2]) { if(!_expect._ok) xorp_throw(InvalidString, c_format("Expect queue violated\nExpect: %sReceived: %s", _expect._list.front()->str().c_str(), _expect._bad->str().c_str())); switch(words.size()) { case 3: break; case 4: if(static_cast<unsigned int>(atoi(words[3].c_str())) != _expect._list.size()) xorp_throw(InvalidString, c_format("Expected list size to be %d actual %u", atoi(words[3].c_str()), (uint32_t)_expect._list.size())); break; default: xorp_throw(InvalidString, c_format("Illegal number of arguments to \"queue\"\n[%s]", line.c_str())); break; } } else if("established" == words[2]) { if(!_established) xorp_throw(InvalidString, c_format("No session established")); } else if("idle" == words[2]) { if(_established) xorp_throw(InvalidString, c_format("Session established")); } else xorp_throw(InvalidString, c_format( "\"queue\" \"established\" \"idle\"accepted not <%s>\n[%s]", words[2].c_str(), line.c_str()));}voidmrtd_traffic_dump(const uint8_t *buf, const size_t len , const TimeVal tv, const string fname){ FILE *fp = fopen(fname.c_str(), "a"); if(0 == fp) XLOG_FATAL("fopen of %s failed: %s", fname.c_str(), strerror(errno)); mrt_header header; header.time = htonl(tv.sec()); header.type = htons(16); header.subtype = htons(1); header.length = htonl(len + sizeof(mrt_update)); if(fwrite(&header, sizeof(header), 1, fp) != 1) XLOG_FATAL("fwrite of %s failed: %s", fname.c_str(), strerror(errno)); mrt_update update; memset(&update, 0, sizeof(update)); update.af = htons(1); /* IPv4 */ if(fwrite(&update, sizeof(update), 1, fp) != 1) XLOG_FATAL("fwrite of %s failed: %s", fname.c_str(), strerror(errno)); if(fwrite(buf, len, 1, fp) != 1) XLOG_FATAL("fwrite of %s failed: %s", fname.c_str(), strerror(errno)); fclose(fp);}template <class A>voidmrtd_routview_dump(const UpdatePacket* p, const IPNet<A>& net, const TimeVal tv, const string fname, const int sequence){ FILE *fp = fopen(fname.c_str(), "a"); if(0 == fp) XLOG_FATAL("fopen of %s failed: %s", fname.c_str(), strerror(errno)); /* ** Figure out the total length of the attributes. */ uint16_t length = 0; list <PathAttribute*>::const_iterator pai; for (pai = p->pa_list().begin(); pai != p->pa_list().end(); pai++) { const PathAttribute* pa; pa = *pai; length += pa->wire_size(); } /* ** Due to alignment problems I can't use a structure overlay. */ uint8_t viewbuf[18 + A::addr_size()], *ptr; mrt_header header; header.time = /*htonl(tv.sec())*/0; header.type = htons(12); if(4 == A::ip_version()) header.subtype = htons(AFI_IPV4); else if(6 == A::ip_version()) header.subtype = htons(AFI_IPV6); else XLOG_FATAL("unknown ip version %d", A::ip_version()); header.length = htonl(length + sizeof(viewbuf)); if(fwrite(&header, sizeof(header), 1, fp) != 1) XLOG_FATAL("fwrite of %s failed: %s", fname.c_str(), strerror(errno)); memset(&viewbuf[0], 0, sizeof(viewbuf)); ptr = &viewbuf[0]; // View number *reinterpret_cast<uint16_t *>(ptr) = 0; ptr += 2; // Sequence number *reinterpret_cast<uint16_t *>(ptr) = htons(sequence); ptr += 2; // Prefix net.masked_addr().copy_out(ptr); ptr += A::addr_size(); // Prefix length *reinterpret_cast<uint8_t *>(ptr) = net.prefix_len(); ptr += 1; // Status *reinterpret_cast<uint8_t *>(ptr) = 0x1; ptr += 1; // Uptime *reinterpret_cast<uint32_t *>(ptr) = htonl(tv.sec()); ptr += 4; // Peer address *reinterpret_cast<uint32_t *>(ptr) = 0; ptr += 4; // Peer AS *reinterpret_cast<uint16_t *>(ptr) = 0; ptr += 2; // Attribute length *reinterpret_cast<uint16_t *>(ptr) = htons(length); ptr += 2; XLOG_ASSERT(ptr == &viewbuf[sizeof(viewbuf)]); if(fwrite(&viewbuf[0], sizeof(viewbuf), 1, fp) != 1) XLOG_FATAL("fwrite of %s failed: %s", fname.c_str(), strerror(errno)); for (pai = p->pa_list().begin(); pai != p->pa_list().end(); pai++) { const PathAttribute* pa; pa = *pai; if(fwrite(pa->data(), pa->wire_size(), 1, fp) != 1) XLOG_FATAL("fwrite of %s failed: %s", fname.c_str(), strerror(errno)); } fclose(fp);}voidtext_traffic_dump(const uint8_t *buf, const size_t len, const TimeVal, const string fname){ FILE *fp = fopen(fname.c_str(), "a"); if(0 == fp) XLOG_FATAL("fopen of %s failed: %s", fname.c_str(), strerror(errno)); fprintf(fp, bgppp(buf, len).c_str()); fclose(fp);}template <class A>voidmrtd_routeview_dump(const UpdatePacket* p, const IPNet<A>& net, const TimeVal& tv, const string fname, int *sequence){ mrtd_routview_dump<A>(p, net, tv, fname, *sequence); (*sequence)++;}template <class A>voidmrtd_debug_dump(const UpdatePacket* p, const IPNet<A>& /*net*/, const TimeVal& tv, const string fname){ size_t len; const uint8_t *buf = p->encode(len); mrtd_traffic_dump(buf, len , tv, fname); delete [] buf;}template <class A>voidtext_debug_dump(const UpdatePacket* p, const IPNet<A>& net, const TimeVal& tv, const string fname){ FILE *fp = fopen(fname.c_str(), "a"); if(0 == fp) XLOG_FATAL("fopen of %s failed: %s", fname.c_str(), strerror(errno)); fprintf(fp, "%s\n%s\n%s\n", net.str().c_str(), tv.pretty_print().c_str(), p->str().c_str()); fclose(fp);}voidmrtd_replay_dump(const UpdatePacket* p, const TimeVal& tv, const string fname){ size_t len; const uint8_t *buf = p->encode(len); mrtd_traffic_dump(buf, len , tv, fname); delete [] buf;}voidtext_replay_dump(const UpdatePacket* p, const TimeVal& /*tv*/, const string fname){ FILE *fp = fopen(fname.c_str(), "a"); if(0 == fp) XLOG_FATAL("fopen of %s failed: %s", fname.c_str(), strerror(errno)); fprintf(fp, "%s\n", p->str().c_str()); fclose(fp);}/*** peer dump <recv/sent> <mtrd/text> <ipv4/ipv6> ** 0 1 2 3 4 **** <traffic/routeview/replay/debug> <fname>** 5 6*/voidPeer::dump(const string& line, const vector<string>& words) throw(InvalidString){ if(words.size() < 6) xorp_throw(InvalidString, c_format("Insufficient arguments:\n[%s]", line.c_str())); /* ** Each peer holds two tries. One holds updates sent the other ** holds updates received. Determine which trie we are about to ** operate on. */ Trie *op; Dumper *dumper; if("sent" == words[2]) { op = &_trie_sent; dumper = &_traffic_sent; } else if("recv" == words[2]) { op = &_trie_recv; dumper = &_traffic_recv; } else xorp_throw(InvalidString, c_format("\"sent\" or \"recv\" accepted not <%s>\n[%s]", words[2].c_str(), line.c_str())); bool mrtd; if("mrtd" == words[3]) { mrtd = true; } else if("text" == words[3]) { mrtd = false; } else xorp_throw(InvalidString, c_format("\"mrtd\" or \"text\" accepted not <%s>\n[%s]", words[3].c_str(), line.c_str())); bool ipv4 = true; if("ipv4" == words[4]) { ipv4 = true; } else if("ipv6" == words[4]) { ipv4 = false; } else xorp_throw(InvalidString, c_format("\"ipv4\" or \"ipv6\" accepted not <%s>\n[%s]", words[4].c_str(), line.c_str())); string filename; if(words.size() == 7) filename = words[6]; if("traffic" == words[5]) { if("" == filename) { dumper->release(); return; } if(mrtd) *dumper = callback(mrtd_traffic_dump, filename); else *dumper = callback(text_traffic_dump, filename); } else if("routeview" == words[5]) { if("" == filename) { xorp_throw(InvalidString, c_format("no filename provided\n[%s]", line.c_str())); } int sequence = 0; if(ipv4) { Trie::TreeWalker_ipv4 tw_ipv4; if(mrtd) tw_ipv4 = callback(mrtd_routeview_dump<IPv4>, filename, &sequence); else tw_ipv4 = callback(text_debug_dump<IPv4>, filename); op->tree_walk_table(tw_ipv4); } else { Trie::TreeWalker_ipv6 tw_ipv6; if(mrtd) tw_ipv6 = callback(mrtd_routeview_dump<IPv6>, filename, &sequence); else tw_ipv6 = callback(text_debug_dump<IPv6>, filename); op->tree_walk_table(tw_ipv6); } } else if("replay" == words[5]) { if("" == filename) { xorp_throw(InvalidString, c_format("no filename provided\n[%s]", line.c_str())); } Trie::ReplayWalker rw; if(mrtd) rw = callback(mrtd_replay_dump, filename); else rw = callback(text_replay_dump, filename); op->replay_walk(rw); } else if("debug" == words[5]) { if("" == filename) { xorp_throw(InvalidString, c_format("no filename provided\n[%s]", line.c_str())); } if(ipv4) { Trie::TreeWalker_ipv4 tw_ipv4; if(mrtd) tw_ipv4 = callback(mrtd_debug_dump<IPv4>, filename); else tw_ipv4 = callback(text_debug_dump<IPv4>, filename); op->tree_walk_table(tw_ipv4); } else { Trie::TreeWalker_ipv6 tw_ipv6; if(mrtd) tw_ipv6 = callback(mrtd_debug_dump<IPv6>, filename); else tw_ipv6 = callback(text_debug_dump<IPv6>, filename); op->tree_walk_table(tw_ipv6); } } else xorp_throw(InvalidString, c_format(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -