00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <arpa/inet.h>
00018 #include <string.h>
00019 #include "Util.h"
00020 #include "RIBTLV.h"
00021
00022 namespace prophet
00023 {
00024
00025 RIBTLV::RIBTLV(const RIBNodeList& nodes,
00026 bool relay, bool custody,
00027 bool internet)
00028 : BaseTLV(BaseTLV::RIB_TLV), nodes_(nodes),
00029 relay_(relay), custody_(custody), internet_(internet)
00030 {
00031 length_ = RIBTLVHeaderSize;
00032 length_ += RIBEntrySize * nodes_.size();
00033 }
00034
00035 RIBTLV::RIBTLV()
00036 : BaseTLV(BaseTLV::RIB_TLV), nodes_(),
00037 relay_(false), custody_(false), internet_(false) {}
00038
00039 size_t
00040 RIBTLV::serialize(u_char* bp, size_t len) const
00041 {
00042
00043 if (bp == NULL || typecode_ != BaseTLV::RIB_TLV) return 0;
00044
00045
00046 if (RIBTLVHeaderSize + RIBEntrySize * nodes_.size() > len) return 0;
00047
00048
00049 length_ = 0;
00050 size_t rib_entry_count = 0;
00051 RIBTLVHeader* hdr = (RIBTLVHeader*) bp;
00052
00053
00054 bp += RIBTLVHeaderSize;
00055 length_ += RIBTLVHeaderSize;
00056 RIBNode* node = NULL;
00057 for (const_iterator i = nodes_.begin(); i != nodes_.end(); i++)
00058 {
00059 node = (*i);
00060
00061 size_t bytes_written = 0;
00062 if ((bytes_written =
00063 write_rib_entry(node->sid_, node->p_value(),
00064 node->relay(), node->custody(),
00065 node->internet_gw(), bp, len)) == 0)
00066 break;
00067
00068 bp += bytes_written;
00069 len -= bytes_written;
00070 length_ += bytes_written;
00071
00072 rib_entry_count++;
00073
00074 node = NULL;
00075 }
00076
00077
00078 hdr->type = typecode_;
00079 hdr->length = htons(length_);
00080 hdr->rib_string_count = htons(rib_entry_count);
00081 hdr->flags = 0;
00082
00083 if (relay_) hdr->flags |= RELAY_NODE;
00084 if (custody_) hdr->flags |= CUSTODY_NODE;
00085 if (internet_) hdr->flags |= INTERNET_GW_NODE;
00086
00087 return length_;
00088 }
00089
00090 void
00091 RIBTLV::decode_flags(u_int8_t flags, bool* relay,
00092 bool* custody, bool* internet)
00093 {
00094
00095 if (relay == NULL || custody == NULL || internet == NULL) return;
00096
00097
00098
00099 *relay = ((flags & RELAY_NODE) == RELAY_NODE);
00100 *custody = ((flags & CUSTODY_NODE) == CUSTODY_NODE);
00101 *internet = ((flags & INTERNET_GW_NODE) == INTERNET_GW_NODE);
00102 }
00103
00104 size_t
00105 RIBTLV::write_rib_entry(u_int16_t sid, double pvalue, bool relay,
00106 bool custody, bool internet, u_char* bp,
00107 size_t len) const
00108 {
00109
00110 if (bp == NULL) return 0;
00111
00112
00113 if (RIBEntrySize > len) return 0;
00114
00115
00116 RIBEntry* rib = (RIBEntry*) bp;
00117 memset(rib,0,RIBEntrySize);
00118 rib->string_id = htons(sid);
00119
00120 rib->pvalue = (u_int8_t) ( (int) (pvalue * (255.0)) ) & 0xff;
00121 rib->flags = 0;
00122 if (relay) rib->flags |= RELAY_NODE;
00123 if (custody) rib->flags |= CUSTODY_NODE;
00124 if (internet) rib->flags |= INTERNET_GW_NODE;
00125
00126 return RIBEntrySize;
00127 }
00128
00129 size_t
00130 RIBTLV::read_rib_entry(u_int16_t* sid, double* pvalue,
00131 bool* relay, bool* custody, bool* internet,
00132 const u_char* bp, size_t len)
00133 {
00134
00135 if (RIBEntrySize > len ||
00136 sid == NULL ||
00137 pvalue == NULL ||
00138 relay == NULL ||
00139 custody == NULL ||
00140 internet == NULL ||
00141 bp == NULL) return 0;
00142
00143
00144 RIBEntry* rib = (RIBEntry*) bp;
00145 *sid = ntohs(rib->string_id);
00146
00147 *pvalue = ((rib->pvalue & 0xff) + 0.0) / (255.0);
00148 decode_flags(rib->flags, relay, custody, internet);
00149 return RIBEntrySize;
00150 }
00151
00152 bool
00153 RIBTLV::deserialize(const u_char* bp, size_t len)
00154 {
00155
00156 if (bp == NULL || typecode_ != BaseTLV::RIB_TLV) return 0;
00157
00158
00159 if (RIBTLVHeaderSize > len) return 0;
00160
00161 RIBTLVHeader* hdr = (RIBTLVHeader*) bp;
00162
00163
00164 if (hdr->type != BaseTLV::RIB_TLV || typecode_ != BaseTLV::RIB_TLV)
00165 return 0;
00166
00167
00168 length_ = ntohs(hdr->length);
00169 if (length_ > len) return 0;
00170
00171
00172 flags_ = hdr->flags;
00173 decode_flags(flags_,&relay_,&custody_,&internet_);
00174 size_t rib_entry_count = ntohs(hdr->rib_string_count);
00175
00176
00177 bp += RIBTLVHeaderSize;
00178 len -= RIBTLVHeaderSize;
00179 size_t amt_read = RIBTLVHeaderSize;
00180
00181
00182 while (rib_entry_count-- > 0)
00183 {
00184 RIBNode remote;
00185 u_int16_t sid = 0;
00186 double pvalue = 0.0;
00187 bool relay = false;
00188 bool custody = false;
00189 bool internet = false;
00190
00191 size_t bytes_read =
00192 read_rib_entry(&sid,&pvalue,&relay,&custody,&internet,bp,len);
00193
00194 if (bytes_read != RIBEntrySize) break;
00195
00196 remote.set_pvalue(pvalue);
00197 remote.set_relay(relay);
00198 remote.set_custody(custody);
00199 remote.set_internet_gw(internet);
00200 remote.sid_ = sid;
00201
00202
00203 nodes_.push_back(new RIBNode(remote));
00204
00205
00206 bp += bytes_read;
00207 len -= bytes_read;
00208 amt_read += bytes_read;
00209 }
00210
00211 return (amt_read == length_);
00212 }
00213
00214 };