blob: a8adbd0e991edd5f034c77c29520f4f67c4ab15a [file] [log] [blame]
Alexander Afanasyevc74a6022011-08-15 20:01:35 -07001/*
2 * File: ndn_fib.cpp
3 * Author: cawka
4 *
5 * Created on December 15, 2010, 1:54 PM
6 */
7
8#include "ndn.h"
9#include "ndn_fib.h"
10
11#include <node.h>
12#include <buffer.h>
13#include <network_ip.h>
14#include <partition.h>
15#include <routing_ospfv2.h>
16#include <routing_bgp.h>
17
18//#define NDN_DEBUG_OSPF 0
19//#define NDN_DEBUG_OSPF_NODES 0
20
21//#define NDN_DUMP_FIB 0
22
23
24NdnFib::NdnFib( Ndn &node ) : _node(node) { }
25
26NdnFib::~NdnFib( ) { }
27
28
29//Find corresponding FIB entry for the given content name
30//Longest match is performed
31FibIterator NdnFib::lookup( const string &name )
32{
33 string prefix=name;
34
35 FibIterator entry;
36 do
37 {
38 entry=_fib.find( prefix );
39
40 prefix = GetLongestNamePrefix( prefix );
41 } while( !isValid(entry) && prefix.size()>0 );
42
43 return entry;
44}
45
46bool NdnFibNexthopSorter::operator()( const FibNexthop &first, const FibNexthop &second )
47{
48 // Right now is a very simple logic.
49 // Probably this logic should be changed later
50 if( first. cost==NETWORK_UNREACHABLE && second.cost>=0 ) return false;
51 if( second.cost==NETWORK_UNREACHABLE && first. cost>=0 ) return true;
52 return first.cost < second.cost;
53}
54
55/**
56 * Update FIB entry
57 * If the entry exists, metric will be updated. Otherwise, new entry will be created
58 *
59 * @param name Prefix
60 * @param interfaceIndex Forwarding interface
61 * @param metric Routing metric
62 * @param nextHop Nexthop node address (IPv4)
63 * @return true if a new entry created, false otherwise
64 */
65bool NdnFib::update( const string &name, int interfaceIndex, int metric, NodeAddress nextHop )
66{
67 FibIterator entry = _fib.find( name );
68 if( isValid(entry) )
69 {
70 FibNexthopIterator nh = VALUE(entry).findNexthop( interfaceIndex );
71
72 if( !VALUE(entry).isValid(nh) )
73 {
74 nh = VALUE(entry).forwardingList.insert( VALUE(entry).forwardingList.begin(),
75 FibNexthop(interfaceIndex,nextHop,metric) );
76 }
77 else
78 {
79 nh->cost = metric;
80 nh->nextHop = nextHop;
81 }
82
83 VALUE(entry).forwardingList.sort( NdnFibNexthopSorter() );
84
85 return false;
86 }
87
88 FibEntry &new_entry = _fib[name];
89 new_entry.forwardingList.push_back( FibNexthop(interfaceIndex,nextHop,metric) );
90
91 for( int interface=0; interface < _node.getNode()->numberInterfaces; interface++ )
92 {
93 NodeAddress src = NetworkIpGetInterfaceAddress( _node.getNode(), interface );
94
95 if( isValidLink(src) && interface!=interfaceIndex )
96 {
97 new_entry.forwardingList.push_back( FibNexthop(interface,0,NETWORK_UNREACHABLE) );
98 }
99 }
100
101 return true;
102}
103
104// helper for update call
105bool NdnFib::update( NodeAddress nodeId, int metric, NodeAddress nextHop )
106{
107 ostringstream os;
108 os << (int)nodeId;
109
110 int interface = NetworkIpGetInterfaceIndexForNextHop( _node.getNode(), nextHop );
111
112 return update( os.str(), interface, metric, nextHop );
113}
114
115// helper for update call
116bool NdnFib::update( NodeAddress nodeId, int interfaceIndex, int metric, NodeAddress nextHop )
117{
118 ostringstream os;
119 os << (int)nodeId;
120
121 int interface = NetworkIpGetInterfaceIndexForNextHop( _node.getNode(), nextHop );
122
123 return update( os.str(), interface, metric, nextHop ); //unknown metric
124}
125
126/**
127 * Invalidate entries in FIB
128 */
129void NdnFib::invalidate( )
130{
131 for( FibRangeIterator fib=_fib.begin(); fib!=_fib.end(); fib++ )
132 {
133 for( FibNexthopIterator nh=VALUE(fib).forwardingList.begin(); nh!=VALUE(fib).forwardingList.end(); nh++ )
134 {
135 nh->cost = NETWORK_UNREACHABLE;
136 }
137 }
138}
139
140//compute and update STO value for Fib Entry (similar to RFC 2988)
141//for now we pick the maximum rto of all forwardings
142void FibEntry::updateSto( )
143{
144 assert( forwardingList.size() > 0 );
145
146 clocktype max = 0;
147
148 for( FibNexthopIterator it = forwardingList.begin();
149 it != forwardingList.end();
150 it++ )
151 {
152 clocktype sto = it->srtt + NDN_RTO_K * it->rttvar;
153
154 if( sto > max )
155 max = sto;
156 }
157
158 this->sto = max;
159}
160
161
162/**
163 * Updating FIB using data from OSPF
164 * @param node
165 * @param interface -2 Invalid OSPF (to purge FIB)
166 * -1 Normal OSPF
167 * 0-N SPF was calcylated using only interface `interface'
168 *
169 * @bug All local networks will always appear in routing table with cost == 1
170 */
171void NdnFib::updateFibFromOSPFv2( int interface )
172{
173 Ospfv2Data* ospf = (Ospfv2Data*)NetworkIpGetRoutingProtocol(_node.getNode(), ROUTING_PROTOCOL_OSPFv2);
174
175 if( interface==-2 ) invalidate( );
176
177#ifdef NDN_DEBUG_OSPF
178 if( interface==-1 ) printf( "Routing/interface costs\n" );
179#endif // NDN_DEBUG_OSPF
180
181#ifdef NDN_DEBUG_OSPF_NODES
182 printf( "-- Node %d (interface %d) --\n", _node.getNode()->nodeId, interface );
183#endif // NDN_DEBUG_OSPF_NODES
184
185 Ospfv2RoutingTableRow* rowPtr = (Ospfv2RoutingTableRow*)
186 BUFFER_GetData(&ospf->routingTable.buffer);
187
188 for (int i = 0; i < ospf->routingTable.numRows; i++)
189 {
190 NodeAddress destNodeId = Ipv4ToNodeId( rowPtr[i].destAddr );
191
192 if( destNodeId!=-1 ) update( destNodeId, rowPtr[i].metric, rowPtr[i].nextHop );
193 }
194
195#ifdef NDN_DUMP_FIB
196 if( interface==-1 ) dump( );
197#endif
198}
199
200void NdnFib::updateFibFromBGP( )
201{
202 BgpData* bgp=(BgpData*)_node.getNode()->appData.exteriorGatewayVar;
203
204 assert( bgp->ip_version == NETWORK_IPV4 );
205
206 invalidate( );
207
208 int i=0;
209 int numEntriesInAdjRibIn=BUFFER_GetCurrentSize( &( bgp->adjRibIn ) )
210 / sizeof(BgpRoutingInformationBase );
211
212 BgpRoutingInformationBase* adjRibInPtr=(BgpRoutingInformationBase*)
213 BUFFER_GetData( &( bgp->adjRibIn ) );
214
215 for( i=0; i < numEntriesInAdjRibIn; i++ )
216 {
217 assert( adjRibInPtr[i].nextHop.networkType == NETWORK_IPV4 );
218
219 NodeAddress destNodeId = Ipv4ToNodeId( GetIPv4Address(adjRibInPtr[i].destAddress.prefix) );
220
221 if( destNodeId!=-1 && adjRibInPtr[i].isValid != FALSE )
222 {
223 char destNodeStr[NDN_MAX_NAME_LENGTH];
224 memset(destNodeStr, 0, NDN_MAX_NAME_LENGTH);
225 sprintf(destNodeStr, "%d", destNodeId);
226
227 update( destNodeId,
228 adjRibInPtr[i].asPathList->pathSegmentLength / 2,
229 GetIPv4Address(adjRibInPtr[i].nextHop) );
230 }
231 }
232
233#ifdef NDN_DUMP_FIB
234 dump( );
235#endif
236}
237
238void NdnFib::updateFibFromIpRouting( )
239{
240 invalidate( );
241
242 for (int i = 0; i < _node.getNode()->partitionData->numNodes; i ++)
243 {
244 if( !_node.getNode()->networkData.networkVar->ndnEnabled ) continue;
245
246 NodeAddress destNode = _node.getNode()->partitionData->nodeData[i]->nodeId;
247 NodeAddress ipv4subnet = NodeIdToIpv4( destNode );
248
249 int interfaceIndex;
250 NodeAddress nextHopAddr;
251 NetworkGetInterfaceAndNextHopFromForwardingTable(
252 _node.getNode(), ipv4subnet, &interfaceIndex, &nextHopAddr );
253
254 if( interfaceIndex != NETWORK_UNREACHABLE )
255 {
256 update( destNode, interfaceIndex, 1, nextHopAddr );
257 }
258 }
259}
260
261
262
263void NdnFib::dump( )
264{
265 if( _node.getNode()->numberInterfaces==1 ) return; // do not dump FIB for `virtual' nodes
266
267 printf( "Node %s: FIB\n", _node.getPrefix().c_str() );
268 printf( " Dest prefix Interfaces(Costs) \n" );
269 printf( "+-------------+--------------------------------------+\n" );
270
271 for( FibRangeIterator fib=_fib.begin(); fib!=_fib.end(); fib++ )
272 {
273 dump( fib );
274 }
275}
276
277void NdnFib::dump( const FibIterator &fib )
278{
279 printf( " %8s ", fib->first.c_str() );
280 for( FibNexthopIterator nh=VALUE(fib).forwardingList.begin(); nh!=VALUE(fib).forwardingList.end(); nh++ )
281 {
282 if( nh!=VALUE(fib).forwardingList.begin() ) printf( "," );
283 printf( "i%d(%d)", nh->interfaceIndex, nh->cost );
284 }
285 printf( "\n" );
286}
287
288void NdnFib::resetProbing()
289{
290 for(FibRangeIterator fib = _fib.begin(); fib != _fib.end(); fib++)
291 VALUE(fib).needsProbing = true;
292}
293
294void NdnFib::updateInterfaceStatus( int interface, int status )
295{
296 for( FibRangeIterator fib = _fib.begin(); fib!=_fib.end(); fib++ )
297 {
298 VALUE(fib).updateStatus( interface, status );
299 }
300}