ns3で全ノードの経路表を集約する

ネットワークシミュレータのns3で、任意のノードにおいてネットワーク全体の完全な経路表が欲しくて、APIあると思ったけどなさそうだった。あるかもしれない。具体的には以下の様なデータ構造が欲しかった。

{
    [ 送信元アドレス, 宛先アドレス ] : [ 中継ノードのアドレス, ... ],
                    .
                    .
                    .
}

今使ってるグラフ理論のライブラリが、この形式で出力してくれるので、同じ形式で保持したい。

以下がコードの断片。ここではL3のルーティングプロトコルはOLSRを使ってる。プロアクティブ型の場合は知らん。OLSRで各ノードが保持するのは (宛先アドレス, ホップ数, インターフェースID, ネクストホップアドレス) の組なので、上のデータ構造をつくるためには全ノードの経路表を覗く必要がある。

typedef std::map<std::pair<Ipv4Address, Ipv4Address>, std::vector<Ipv4Address> > Tables; 
typedef std::map<std::pair<Ipv4Address, Ipv4Address>, Ipv4Address> NextHops;
Tables tables;
NextHops next_hops;

for (uint32_t i=0; i<NodeList::GetNNodes (); ++i)
{
    Ptr<Node> node = NodeList::GetNode (i);
    Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
    Ptr<Ipv4ListRouting> list = DynamicCast<Ipv4ListRouting> (ipv4->GetRoutingProtocol ());
    for (uint32_t j=0; j<list->GetNRoutingProtocols (); ++j)
    {
        int16_t priority;
        Ptr<Ipv4RoutingProtocol> anonymous = list->GetRoutingProtocol (j, priority);
        if (DynamicCast<olsr::RoutingProtocol> (anonymous))
        {
            Ptr<olsr::RoutingProtocol> olsr = DynamicCast<olsr::RoutingProtocol> (anonymous);
            std::vector<RoutingTableEntry> table = olsr->GetRoutingTableEntries ();
            for (uint32_t j=0; k<table.size (); ++k)
            {
                RoutingTableEntry entry = table[k];
                uint32_t intrf = entry.interface;
                std::pair<Ipv4Address, Ipv4Address> key;
                key.first = (ipv4->GetAddress (intrf, 0).GetLocal ());
                key.second = entry.destAddr;
                std::pair<std::pair<Ipv4Address, Ipv4Address>, Ipv4Address> elem (key, entry.nextAddr);
                next_hops.insert (elem);
            }
            break; //OLSR found
        }
    }
}

for (NextHops::iterator it = next_hops.begin (); it!=next_hops.end (); ++it)
{
    Ipv4Address src = it->first.first;
    Ipv4Address dst = it->first.second;
    Ipv4Address nxt = it->second;
    std::pair<Ipv4Address, Ipv4Address> key (src, dst);
    std::vector<Ipv4Address> intermediates;
    intermediates.push_back (nxt);
    while (nxt != dst)
    {
        nxt = next_hops[std::pair<Ipv4Address, Ipv4Address> (nxt, dst)];
        intermediates.push_back (nxt);
    }
    std::pair<std::pair<Ipv4Address, Ipv4Address>, std::vector<Ipv4Address> > elem (key, intermediates);
    tables.insert (elem);
}

for (Tables::iterator it = tables.begin (); it!=tables.end (); ++it)
{
    std::cout << "SOURCE : "<< it->first.first << ", DESTINATION : " << it->first.second << std::endl;
    std::cout << "INTERMEDIATE NODES : ";
    std::vector<Ipv4Address> intermediates = it->second;
    for (std::vector<Ipv4Address>::iterator addr=intermediates.begin (); addr!=intermediates.end (); ++addr)
    {
        std::cout << *addr << " ";
    }
    std::cout << std::endl << std::endl;
}

たとえば下みたいなのが出る。中継ノードの最後は宛先ノードで終わるようにした。これで中継ノード数がホップ数になる。

SRC : 10.1.1.1, DST : 10.1.1.2
INTERMEDIATE NODES : 10.1.1.96 10.1.1.30 10.1.1.27 10.1.1.34 10.1.1.18 10.1.1.51 10.1.1.69 10.1.1.25 10.1.1.2 

SRC : 10.1.1.1, DST : 10.1.1.3
INTERMEDIATE NODES : 10.1.1.96 10.1.1.30 10.1.1.27 10.1.1.34 10.1.1.18 10.1.1.51 10.1.1.95 10.1.1.20 10.1.1.12 10.1.1.55 10.1.1.40 10.1.1.59 10.1.1.70 10.1.1.3 

SRC : 10.1.1.1, DST : 10.1.1.4
INTERMEDIATE NODES : 10.1.1.96 10.1.1.30 10.1.1.27 10.1.1.34 10.1.1.18 10.1.1.51 10.1.1.69 10.1.1.25 10.1.1.92 10.1.1.29 10.1.1.98 10.1.1.58 10.1.1.4 

SRC : 10.1.1.1, DST : 10.1.1.5
INTERMEDIATE NODES : 10.1.1.96 10.1.1.30 10.1.1.5 

SRC : 10.1.1.1, DST : 10.1.1.6
INTERMEDIATE NODES : 10.1.1.96 10.1.1.30 10.1.1.27 10.1.1.34 10.1.1.18 10.1.1.51 10.1.1.69 10.1.1.25 10.1.1.6 

SRC : 10.1.1.1, DST : 10.1.1.7
INTERMEDIATE NODES : 10.1.1.96 10.1.1.30 10.1.1.27 10.1.1.34 10.1.1.18 10.1.1.51 10.1.1.69 10.1.1.25 10.1.1.92 10.1.1.29 10.1.1.98 10.1.1.7 

(略)

配置は下みたいな感じ。

http://farm4.staticflickr.com/3757/10066465633_6ea8ffede9_c.jpg

注意点として、経路が収束するのに結構時間がかかるので、最低でも30チックくらいは待ってから実行した方がいい。ノード数100くらいになると多分足りなくて、60チックくらいにしてる。
もちろん静的配置の場合で。それから、上のコードの実行にもかなり時間がかかるから、やっぱり移動性あると厳しいと思う。