📄 peer.cc
字号:
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_bytelen()], *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", XORP_UINT_CAST(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 embed_16(ptr, 0); ptr += 2; // Sequence number embed_16(ptr, sequence); ptr += 2; // Prefix net.masked_addr().copy_out(ptr); ptr += A::addr_bytelen(); // Prefix length *reinterpret_cast<uint8_t *>(ptr) = net.prefix_len(); ptr += 1; // Status *reinterpret_cast<uint8_t *>(ptr) = 0x1; ptr += 1; // Uptime embed_32(ptr, tv.sec()); ptr += 4; // Peer address embed_32(ptr, 0); ptr += 4; // Peer AS embed_16(ptr, 0); ptr += 2; // Attribute length embed_16(ptr, 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];#ifdef HOST_OS_WINDOWS // // If run from an MSYS shell, we need to perform UNIX->NT path // conversion and expansion of /tmp by ourselves. // filename = unix_path_to_native(filename); static const char tmpdirprefix[] = "\\tmp\\"; if (0 == _strnicmp(filename.c_str(), tmpdirprefix, strlen(tmpdirprefix))) { char tmpexp[MAXPATHLEN]; size_t size = GetTempPathA(sizeof(tmpexp), tmpexp); if (size == 0 || size >= sizeof(tmpexp)) { xorp_throw(InvalidString, c_format("Internal error during tmpdir expansion")); } filename.replace(0, strlen(tmpdirprefix), string(tmpexp)); }#endif 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("\"traffic\" or \"routeview\" or \"replay\" or \"debug\" accepted not <%s>\n[%s]", words[5].c_str(), line.c_str()));}boolcompare_packets(const BGPPacket *base_one, const BGPPacket *base_two){ if(base_one->type() != base_two->type()) return false; switch(base_one->type()) { case MESSAGETYPEOPEN: { const OpenPacket *one = dynamic_cast<const OpenPacket *>(base_one); const OpenPacket *two = dynamic_cast<const OpenPacket *>(base_two); return *one == *two; } break; case MESSAGETYPEUPDATE: { const UpdatePacket *one = dynamic_cast<const UpdatePacket *>(base_one); const UpdatePacket *two = dynamic_cast<const UpdatePacket *>(base_two); return *one == *two; } break; case MESSAGETYPENOTIFICATION: { const NotificationPacket *one = dynamic_cast<const NotificationPacket *>(base_one); const NotificationPacket *two = dynamic_cast<const NotificationPacket *>(base_two); return *one == *two; } break; case MESSAGETYPEKEEPALIVE: { const KeepAlivePacket *one = dynamic_cast<const KeepAlivePacket *>(base_one); const KeepAlivePacket *two = dynamic_cast<const KeepAlivePacket *>(base_two); return *one == *two; } break; default: XLOG_FATAL("Unexpected BGP message type %d", base_one->type()); } return false;}/*** We just received a BGP message. Check our expected queue for a match.*/voidPeer::check_expect(BGPPacket *rec){ /* ** If its already gone bad just return. */ if(!_expect._ok) return; /* ** If there is nothing on the queue return. */ if(_expect._list.empty()) return; const BGPPacket *exp = _expect._list.front(); debug_msg("Expecting: %s\n", exp->str().c_str()); if(compare_packets(rec, exp)) { _expect._list.pop_front(); delete exp; } else { debug_msg("Received packet %s did not match Expected\n", rec->str().c_str()); _expect._ok = false; /* ** Need to go through this performance in order to copy a ** packet. */ size_t rec_len; const uint8_t *rec_buf = rec->encode(rec_len); switch(rec->type()) { case MESSAGETYPEOPEN: { OpenPacket *pac = new OpenPacket(rec_buf, rec_len); _expect._bad = pac; } break; case MESSAGETYPEUPDATE: { UpdatePacket *pac = new UpdatePacket(rec_buf, rec_len); _expect._bad = pac; } break; case MESSAGETYPENOTIFICATION: { NotificationPacket *pac = new NotificationPacket(rec_buf, rec_len); _expect._bad = pac; } break; case MESSAGETYPEKEEPALIVE: _expect._bad = new KeepAlivePacket(rec_buf, rec_len); break; default: XLOG_FATAL("Unexpected BGP message type %d", rec->type()); } delete [] rec_buf; }}voidPeer::xrl_callback(const XrlError& error, const char *comment){ debug_msg("callback %s %s\n", comment, error.str().c_str()); XLOG_ASSERT(0 != _busy); _busy--; if(XrlError::OKAY() != error) { XLOG_WARNING("callback: %s %s", comment, error.str().c_str()); _session = false; _established = false; }}voidPeer::xrl_callback_connected(const XrlError& error, const char *comment){ debug_msg("callback_connected %s %s\n", comment, error.str().c_str()); if(XrlError::OKAY() == error) { _connected = true; } else { _connected = false; } xrl_callback(error, comment);}/*** This method receives data from the BGP process under test via the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -