📄 bridgemessage.cc
字号:
/* * bridgemessage.{cc,hh} -- parse IEEE 802.1d Ethernet bridge messages * John Jannotti * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * * 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 "bridgemessage.hh"#include <click/glue.hh>#include <click/confparse.hh>CLICK_DECLSStringBridgeMessage::s(String tag) const { // static assertion on message size static_assert(sizeof(BridgeMessage::wire) == 60); char* buf = new char[256]; String s; sprintf(buf, "%s %16s:%04hx: %2s %x -> %16s m/h/d: %hx/%hx/%hx", tag.cc(), cp_unparse_unsigned64(_bridge_id,16,false).cc(), _port_id, _tc ? "TC" : "tc", _cost, cp_unparse_unsigned64(_root,16,false).cc(), _max_age, _hello_time, _forward_delay); s = buf; delete [] buf; return s;}#define COMPARE(a,b,c) if ((a) != (b)) return ((a) < (b)) ? (c) : -(c);intBridgeMessage::compare(const BridgeMessage* other) const { COMPARE(_root, other->_root, 4); COMPARE(_cost, other->_cost, 3); COMPARE(_bridge_id, other->_bridge_id, 2); COMPARE(_port_id, other->_port_id, 1); return 0;}intBridgeMessage::compare(const BridgeMessage::wire* other) const { COMPARE(_root, ntohq(other->root), 4); COMPARE(_cost, ntohl(other->cost), 3); COMPARE(_bridge_id, ntohq(other->bridge_id), 2); COMPARE(_port_id, ntohs(other->port_id), 1); return 0;}intBridgeMessage::compare(const BridgeMessage* other, uint64_t _bridge_id, uint16_t _port_id) const { COMPARE(_root, other->_root, 4); COMPARE(_cost, other->_cost, 3); COMPARE(_bridge_id, other->_bridge_id, 2); COMPARE(_port_id, other->_port_id, 1); return 0;}voidBridgeMessage::reset(uint64_t bridge_id) { _root = _bridge_id = bridge_id; _cost = 0; _timestamp._sec = ~(1 << 31); // Never expire _tc = false; _max_age = 20; _hello_time = 2; _forward_delay = 15;}/* If message's timestamp is older than cutoff, make the message as bad as possible. */bool BridgeMessage::expire(const Timestamp& cutoff) { if (_timestamp > cutoff) return false; expire(); return true;}/* If t is after the message's timestamp, make the message as bad as possible. */void BridgeMessage::expire() { _root = _bridge_id = ~(uint64_t)0; // Worst possible _cost = ~(uint16_t)0; // Worst possible _timestamp._sec = ~(1 << 31); // Never expire _tc = false;}voidBridgeMessage::from_wire(const BridgeMessage::wire* msg) { _root = ntohq(msg->root); _cost = ntohl(msg->cost); _bridge_id = ntohq(msg->bridge_id); _port_id = ntohs(msg->port_id); _timestamp = Timestamp::now(); // How stale is this message? int lateness = (ntohs(msg->message_age) * 1000000)/256; _timestamp -= Timestamp::make_usec(lateness); _tc = msg->tc; // Propagate Parameters _max_age = ntohs(msg->max_age) / 256; _hello_time = ntohs(msg->hello_time) / 256; _forward_delay = ntohs(msg->forward_delay) / 256;}voidBridgeMessage::to_wire(BridgeMessage::wire* msg) const { prep_msg(msg); msg->length = htons(38); // Data + 3 (for sap and ctl, I guess) msg->type = 0; // CONFIRM msg->tca = 0; msg->reserved = 0; msg->tc = _tc; msg->root = htonq(_root); msg->cost = htonl(_cost); // Actually, these two will be overwritten msg->bridge_id = htonq(_bridge_id); msg->port_id = htons(_port_id); // How stale is this message? if (_timestamp._sec == ~(1<<31)) { // Special "do not expire" value msg->message_age = htons(0); } else { Timestamp t = Timestamp::now() - _timestamp; msg->message_age = htons((t.usec() * 256)/1000000); msg->message_age += htons(t.sec() * 256); } // Propagate Parameters msg->max_age = htons(256 * _max_age); msg->hello_time = htons(256 * _hello_time); msg->forward_delay = htons(256 * _forward_delay);}StringBridgeMessage::wire::s(String tag) const { char* buf = new char[256]; String s; /* if (protocol || version) click_chatter("PROTOCOL: %hx VERSION: %hx", htons(protocol), htons(version)); */ if (type == 128) sprintf(buf, "%s TCM", tag.cc()); else sprintf(buf, "%s %3s %16s:%04hx: %3s %2s %08x -> %16s " "a/m/h/d: %hx/%hx/%hx/%hx", tag.cc(), type ? "???" : "CFG", cp_unparse_unsigned64(ntohq(bridge_id),16,false).cc(), ntohs(port_id), tca ? "TCA":"tca", tc ? "TC" : "tc", ntohl(cost), cp_unparse_unsigned64(ntohq(root),16,false).cc(), ntohs(message_age), ntohs(max_age), ntohs(hello_time), ntohs(forward_delay)); s = buf; delete [] buf; return s;}void BridgeMessage::prep_msg(BridgeMessage::wire* msg) { memset(msg, 0, sizeof(*msg)); // REMOVE, HELPFUL FOR DEBUGGING memcpy(msg->dst, _all_bridges, 6); msg->sap = 0x4242; // Bridge Messaging Protocol msg->ctl = 3; // "Unnumbered information" msg->protocol = 0; msg->version = 0;}void BridgeMessage::fill_tcm(BridgeMessage::wire* msg) { prep_msg(msg); msg->length = htons(7); msg->type = 128;}uint8_t BridgeMessage::_all_bridges[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00};CLICK_ENDDECLSELEMENT_REQUIRES(int64)ELEMENT_PROVIDES(EtherSwitchBridgeMessage)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -