test/netlink-socket-test.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 05 May 2011 09:28:21 +0200
changeset 66 2fe1f3e576c9
parent 63 e89dca438df6
permissions -rw-r--r--
make it somewhat build sanely
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2008 Liu Jian
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Author: Liu Jian <liujatp@gmail.com>
    19  *         Hajime Tazaki <tazaki@sfc.wide.ad.jp>
    20  */
    21 
    22 #include "ns3/test.h"
    23 #include "ns3/simulator.h"
    24 #include "ns3/packet.h"
    25 #include "ns3/node-container.h"
    26 #include "ns3/internet-stack-helper.h"
    27 #include "ns3/point-to-point-helper.h"
    28 #include "ns3/ipv4-address-helper.h"
    29 #include "ns3/ipv4-global-routing-helper.h"
    30 #include "ns3/socket-factory.h"
    31 #include "ns3/string.h"
    32 #include "ns3/assert.h"
    33 #include "ns3/log.h"
    34 #include "ns3/socket.h"
    35 #include "netlink-message.h"
    36 #include "netlink-socket-address.h"
    37 #include <sys/socket.h>
    38 #include <string>
    39 #include <list>
    40 
    41 
    42 NS_LOG_COMPONENT_DEFINE ("NetlinkSocketTest");
    43 
    44 namespace ns3 {
    45 
    46 
    47 class NetlinkSocketTestCase: public TestCase
    48 {
    49 public:
    50   NetlinkSocketTestCase ();
    51   virtual void DoRun (void);
    52 private:
    53   NetlinkMessage BuildGetMessage (uint16_t type, uint16_t flags);
    54   NetlinkMessage BuildAddressMessage (uint16_t type, uint16_t flags);
    55   NetlinkMessage BuildLinkChangeMessage (uint16_t type, uint16_t flags);
    56   NetlinkMessage BuildRouteMessage (uint16_t type, uint16_t flags);
    57   MultipartNetlinkMessage BuildMultipartMessage (uint16_t type, uint16_t flags);
    58 
    59   bool CheckIsAck (NetlinkMessage nlmsg);
    60   bool CheckIsDump (MultipartNetlinkMessage nlmsg);
    61   bool CheckIsEqual (NetlinkMessageHeader nhr1, NetlinkMessageHeader nhr2);
    62   bool CheckIsEqual (NetlinkMessage nlmsg1, NetlinkMessage nlmsg2);
    63   bool CheckIsEqual (MultipartNetlinkMessage mulmsg1, MultipartNetlinkMessage mulmsg2);
    64 
    65   void TestNetlinkSerialization ();
    66   void TestInterfaceAddressMessage ();
    67   void TestInferfaceInfoMessage ();
    68   void TestRouteMessage ();
    69   void TestBroadcastMessage ();
    70 
    71   void ReceiveUnicastPacket (Ptr<Socket> socket);
    72   void ReceiveMulticastPacket (Ptr<Socket> socket);
    73   void SendCmdToKernel (uint16_t type);
    74   void SendNetlinkMessage (NetlinkMessage nlmsg);
    75   void MonitorKernelChanges ();
    76   Ptr<SocketFactory> CreateNetlinkFactory (void);
    77 
    78   std::list<MultipartNetlinkMessage> m_unicastList;
    79   std::list<MultipartNetlinkMessage> m_multicastList;
    80   Ptr<Socket> m_cmdSock;
    81   Ptr<Socket> m_groupSock;  
    82   int m_pid;
    83 };
    84 
    85 
    86 
    87 NetlinkMessage
    88 NetlinkSocketTestCase::BuildGetMessage (uint16_t type, uint16_t flags)
    89 {
    90   NS_ASSERT (type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETROUTE);
    91 
    92   NetlinkMessage nlmsg;
    93   flags |= (NETLINK_MSG_F_DUMP|NETLINK_MSG_F_ACK|NETLINK_MSG_F_REQUEST);
    94   nlmsg.SetHeader (NetlinkMessageHeader (type, flags, 0, 0));
    95   GeneralMessage genmsg;
    96   genmsg.SetFamily (AF_INET);
    97   nlmsg.SetGeneralMessage (genmsg);
    98   //no attributes appended
    99   return nlmsg;
   100 }
   101 
   102 NetlinkMessage
   103 NetlinkSocketTestCase::BuildAddressMessage (uint16_t type, uint16_t flags)
   104 {
   105   NS_ASSERT (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR);
   106 
   107   flags |= (NETLINK_MSG_F_ACK|NETLINK_MSG_F_REQUEST); 
   108   if (type == NETLINK_RTM_NEWADDR)
   109     {
   110       flags |= NETLINK_MSG_F_CREATE;
   111     }
   112 
   113   NetlinkMessage nlmsg;
   114   //set header
   115   nlmsg.SetHeader (NetlinkMessageHeader (type, flags, 0, 0));
   116 
   117   //set service module
   118   InterfaceAddressMessage ifamsg;
   119   ifamsg.SetFamily (AF_INET);
   120   ifamsg.SetLength (24);
   121   ifamsg.SetInterfaceIndex (3);
   122 
   123   ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL, ADDRESS, Ipv4Address("192.168.0.1")));
   124   ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS,ADDRESS, Ipv4Address("192.168.0.2")));
   125   ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL, STRING, "TESTSTRING"));
   126 
   127   nlmsg.SetInterfaceAddressMessage (ifamsg);
   128   return nlmsg;
   129 }
   130 
   131 NetlinkMessage
   132 NetlinkSocketTestCase::BuildLinkChangeMessage (uint16_t type, uint16_t flags)
   133 {
   134   NetlinkMessage nlmsg;
   135   NS_LOG_WARN (this << type << flags << " not supported");
   136   return nlmsg;
   137 }
   138 
   139 NetlinkMessage
   140 NetlinkSocketTestCase::BuildRouteMessage (uint16_t type, uint16_t flags)
   141 {
   142   NS_ASSERT (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE);
   143 
   144   flags |= (NETLINK_MSG_F_ACK|NETLINK_MSG_F_REQUEST); 
   145   if (type == NETLINK_RTM_NEWROUTE)
   146     {
   147       flags |= NETLINK_MSG_F_CREATE;
   148     }
   149 
   150   NetlinkMessage nlmsg;
   151   //set header
   152   nlmsg.SetHeader (NetlinkMessageHeader (type, flags, 0, m_pid));
   153 
   154   //set service module
   155   RouteMessage rtmsg;
   156   //set attribute
   157   rtmsg.SetFamily (AF_INET);
   158   rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, Ipv4Address ("192.168.0.10")));
   159   rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, Ipv4Address ("192.168.2.10")));
   160   rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, Ipv4Address ("10.1.1.10")));
   161   rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, (uint32_t)2));
   162 
   163   nlmsg.SetRouteMessage(rtmsg);
   164   return nlmsg;
   165 }
   166 
   167 MultipartNetlinkMessage
   168 NetlinkSocketTestCase::BuildMultipartMessage (uint16_t type, uint16_t flags)
   169 {
   170   //usually multi-part message used for message dump, kernel return to user space for NETLINK_RTM_GETxxx
   171   //type = NETLINK_RTM_NEWxxx, flags = NETLINK_MSG_F_MULTI, terminated by NETLINK_MSG_DONE, 
   172   //here this example contain 2 NETLINK_MSG_F_MULTI
   173   NS_ASSERT (flags&NETLINK_MSG_F_MULTI);
   174 
   175   MultipartNetlinkMessage nlmsg;
   176   NetlinkMessage nlmsg1, nlmsg2, nlmsg3;
   177   nlmsg1 = BuildAddressMessage (NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI);
   178   nlmsg.AppendMessage (nlmsg1);
   179   //the first nlmsg
   180   nlmsg2 = BuildRouteMessage (NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI);
   181   nlmsg.AppendMessage (nlmsg2);
   182   //the second nlmsg
   183   nlmsg3.SetHeader (NetlinkMessageHeader (NETLINK_MSG_DONE, flags, 1, m_pid));
   184   nlmsg.AppendMessage (nlmsg3);
   185 
   186   return nlmsg;
   187 }
   188 
   189 
   190 
   191 
   192 bool
   193 NetlinkSocketTestCase::CheckIsAck (NetlinkMessage nlmsg)
   194 {
   195   return (nlmsg.GetMsgType () == NETLINK_MSG_ERROR && nlmsg.GetErrorMessage ().GetError () == 0);
   196 }
   197 
   198 bool
   199 NetlinkSocketTestCase::CheckIsDump (MultipartNetlinkMessage mulmsg)
   200 {
   201   return (mulmsg.GetNMessages () > 0 && mulmsg.GetMessage (0).GetHeader ().GetMsgFlags () & NETLINK_MSG_F_MULTI &&
   202           mulmsg.GetMessage (mulmsg.GetNMessages () - 1).GetMsgType () == NETLINK_MSG_DONE); 
   203 }
   204 
   205 bool
   206 NetlinkSocketTestCase::CheckIsEqual (NetlinkMessageHeader nhr1, NetlinkMessageHeader nhr2)
   207 {
   208   return (nhr1.GetMsgType () == nhr2.GetMsgType () && nhr1.GetMsgFlags () == nhr2.GetMsgFlags ()
   209           && nhr1.GetMsgLen () == nhr2.GetMsgLen ());
   210 }
   211 
   212 bool
   213 NetlinkSocketTestCase::CheckIsEqual (NetlinkMessage nlmsg1, NetlinkMessage nlmsg2)
   214 {
   215   return CheckIsEqual (nlmsg1.GetHeader (), nlmsg2.GetHeader ());
   216 }
   217 
   218 bool
   219 NetlinkSocketTestCase::CheckIsEqual (MultipartNetlinkMessage mulmsg1, MultipartNetlinkMessage mulmsg2)
   220 {
   221   if (mulmsg1.GetNMessages () != mulmsg2.GetNMessages ())
   222     return false;
   223 
   224   for (uint32_t i = 0; i < mulmsg1.GetNMessages(); i ++)
   225     {
   226       if (!CheckIsEqual (mulmsg1.GetMessage (i), mulmsg2.GetMessage (i)))
   227         {
   228           return false;
   229         }
   230     }
   231   return true;  
   232 }
   233 
   234 void
   235 NetlinkSocketTestCase::TestNetlinkSerialization ()
   236 {
   237   MultipartNetlinkMessage multinlmsg1, multinlmsg2;
   238   Ptr<Packet> p = Create<Packet> ();
   239 
   240   multinlmsg1 = BuildMultipartMessage (NETLINK_RTM_NEWADDR, NETLINK_MSG_F_REQUEST|NETLINK_MSG_F_MULTI);
   241   p->AddHeader (multinlmsg1);
   242   p->RemoveHeader (multinlmsg2);
   243   NS_TEST_ASSERT_MSG_EQ (CheckIsEqual (multinlmsg1, multinlmsg2), true, "Should be equal");
   244 }
   245 void
   246 NetlinkSocketTestCase::TestInterfaceAddressMessage ()
   247 {
   248   MultipartNetlinkMessage dump1, dump2, dump3;
   249   NetlinkMessage nlmsg1,nlmsg2;
   250 
   251   //dump interface address
   252   SendNetlinkMessage (BuildGetMessage (NETLINK_RTM_GETADDR, 0));
   253   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue should be 1 (RTM_GETADDR)");
   254   dump1 = m_unicastList.front ();
   255   m_unicastList.pop_front ();
   256   NS_TEST_ASSERT_MSG_EQ (CheckIsDump (dump1), true, "Should be dump msg");
   257 
   258   //add interface address
   259   // Not implemented yet (100325)
   260 #if 0
   261   SendNetlinkMessage (BuildAddressMessage (NETLINK_RTM_NEWADDR,0));
   262   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue should be 1 (RTM_NEWADDR)");
   263   nlmsg1 = m_unicastList.front ().GetMessage (0);
   264   m_unicastList.pop_front ();
   265   NS_TEST_ASSERT_MSG_EQ (CheckIsAck (nlmsg1), true, "msg should be Ack");
   266 #endif
   267 
   268   //dump interface address
   269   SendNetlinkMessage (BuildGetMessage (NETLINK_RTM_GETADDR, 0));
   270   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue should be 1 (RTM_GETADDR)");
   271   dump2 = m_unicastList.front ();
   272   m_unicastList.pop_front ();
   273   NS_TEST_ASSERT_MSG_EQ (CheckIsDump (dump2), true, "msg should be dump");
   274 
   275   //del interface address
   276   // Not implemented yet (100325)
   277 #if 0
   278   SendNetlinkMessage (BuildAddressMessage (NETLINK_RTM_DELADDR,0));
   279   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue size should be 1 (RTM_DELADDR)");
   280   nlmsg2 = m_unicastList.front ().GetMessage (0);
   281   m_unicastList.pop_front ();
   282   NS_TEST_ASSERT_MSG_EQ (CheckIsAck (nlmsg2), true, "msg should be Ack");
   283 #endif
   284 
   285   //dump interface address
   286   SendNetlinkMessage (BuildGetMessage (NETLINK_RTM_GETADDR, 0));
   287   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue size should be 1 (RTM_GETADDR)");
   288   dump3 = m_unicastList.front ();
   289   m_unicastList.pop_front ();
   290   NS_TEST_ASSERT_MSG_EQ (CheckIsDump (dump3), true, "msg should be dump");
   291 
   292   NS_TEST_ASSERT_MSG_EQ (CheckIsEqual (dump1, dump3), true, "Dump msg should be same");
   293 }
   294 
   295 
   296 void
   297 NetlinkSocketTestCase::TestRouteMessage ()
   298 {
   299   MultipartNetlinkMessage dump1, dump2, dump3;
   300   NetlinkMessage nlmsg1,nlmsg2;
   301 
   302   //dump route entry
   303   SendNetlinkMessage (BuildGetMessage (NETLINK_RTM_GETROUTE, 0));
   304   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue size should be 1 (RTM_GETROUTE)");
   305   dump1 = m_unicastList.front ();
   306   m_unicastList.pop_front ();
   307   NS_TEST_ASSERT_MSG_EQ (CheckIsDump (dump1), true, "msg should be dump");
   308 
   309   //add route entry
   310   SendNetlinkMessage (BuildRouteMessage (NETLINK_RTM_NEWROUTE,0));
   311   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue size should be 1 (RTM_NEWROUTE)");
   312   nlmsg1 = m_unicastList.front ().GetMessage (0);
   313   m_unicastList.pop_front ();
   314   NS_TEST_ASSERT_MSG_EQ (CheckIsAck (nlmsg1), true, "msg should be Ack");
   315 
   316   //dump route entry
   317   SendNetlinkMessage (BuildGetMessage (NETLINK_RTM_GETROUTE, 0));
   318   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue size should be 1 (RTM_GETROUTE)");
   319   dump2 = m_unicastList.front ();
   320   m_unicastList.pop_front ();
   321   NS_TEST_ASSERT_MSG_EQ (CheckIsDump (dump2), true, "msg should be dump");
   322 
   323   //del route entry
   324   SendNetlinkMessage (BuildRouteMessage (NETLINK_RTM_DELROUTE, 0));
   325   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue size should be 1 (RTM_DELROUTE)");
   326   nlmsg2 = m_unicastList.front ().GetMessage (0);
   327   m_unicastList.pop_front ();
   328   NS_TEST_ASSERT_MSG_EQ (CheckIsAck (nlmsg2), true, "msg should be Ack");
   329 
   330   //dump route entry
   331   SendNetlinkMessage (BuildGetMessage (NETLINK_RTM_GETROUTE, 0));
   332   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue size should be 1 (RTM_GETROUTE)");
   333   dump3 = m_unicastList.front ();
   334   m_unicastList.pop_front ();
   335   NS_TEST_ASSERT_MSG_EQ (CheckIsDump (dump3), true, "msg should be dump");
   336 
   337   NS_TEST_ASSERT_MSG_EQ (CheckIsEqual (dump1, dump3), true, "msg should be same");
   338 }
   339 
   340 void
   341 NetlinkSocketTestCase::TestInferfaceInfoMessage ()
   342 {
   343   //now netlink not support NEWLINK/DELLINK yet
   344   MultipartNetlinkMessage multinlmsg;
   345 
   346   //dump interface address
   347   SendNetlinkMessage (BuildGetMessage (NETLINK_RTM_GETLINK, 0));
   348   NS_TEST_ASSERT_MSG_EQ (m_unicastList.size (), 1, "queue size should be 1 (RTM_GETLINK)");
   349   multinlmsg = m_unicastList.front ();
   350   m_unicastList.pop_front ();
   351   NS_TEST_ASSERT_MSG_EQ (CheckIsDump (multinlmsg), true, "msg should be dump");
   352 
   353   NS_TEST_ASSERT_MSG_EQ ((multinlmsg.GetNMessages () > 1) && (multinlmsg.GetMessage (0).GetMsgType () == NETLINK_RTM_NEWLINK),
   354                         true, "msg might be incorrect");
   355 }
   356 
   357 void
   358 NetlinkSocketTestCase::TestBroadcastMessage ()
   359 {
   360   //at 2Xs, m_cmdSock send an request to kernel to add/del an interface address
   361   //and an route entry,  the m_groupSock will recv the changed information
   362   //through the broadcast way  
   363   m_multicastList.clear();
   364   Simulator::Schedule (Seconds (1), &NetlinkSocketTestCase::MonitorKernelChanges, this);
   365   // Not implemented yet (100325)
   366 #if 0
   367   Simulator::Schedule (Seconds (2), &NetlinkSocketTestCase::SendCmdToKernel, this, NETLINK_RTM_NEWADDR);
   368 #endif
   369   Simulator::Schedule (Seconds (4), &NetlinkSocketTestCase::SendCmdToKernel, this, NETLINK_RTM_NEWROUTE);
   370   // Not implemented yet (100325)
   371 #if 0
   372   Simulator::Schedule (Seconds (6), &NetlinkSocketTestCase::SendCmdToKernel, this, NETLINK_RTM_DELADDR);
   373 #endif
   374   Simulator::Schedule (Seconds (8), &NetlinkSocketTestCase::SendCmdToKernel, this, NETLINK_RTM_DELROUTE);
   375 };
   376 
   377 
   378 void
   379 NetlinkSocketTestCase::SendNetlinkMessage (NetlinkMessage nlmsg)
   380 {
   381 #if 1
   382   Ptr<Packet> p = Create<Packet> ();
   383   p->AddHeader (MultipartNetlinkMessage (nlmsg));
   384 #else
   385   char buf[20] = {0x14,0x00,0x00,0x00,0x12,0x00,0x05,0x03,
   386                   0x34,0xb2,0xf5,0x47,0x01,0x00,0x00,0x00,
   387                   0x00,0x00,0x00,0x00};
   388   uint32_t count = 20;
   389   Ptr<Packet> p = ns3::Create<Packet> ((const uint8_t *)buf, (uint32_t)count);
   390 #endif
   391   
   392   m_cmdSock->Send (p);
   393 }
   394 void
   395 NetlinkSocketTestCase::SendCmdToKernel (uint16_t type)
   396 {
   397   NS_LOG_INFO ("At = " <<  Simulator::Now ().GetSeconds () <<"s, user send cmd to kernel, cmd = " << type);
   398 
   399   if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
   400     {
   401       SendNetlinkMessage (BuildAddressMessage (type, 0));
   402     }
   403   else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE)
   404     {
   405       SendNetlinkMessage (BuildRouteMessage (type, 0));
   406     }
   407   else
   408     {
   409       NS_LOG_ERROR ("netlink cmd not support , type = " << type);
   410     }  
   411 }
   412 
   413 
   414 void
   415 NetlinkSocketTestCase::ReceiveUnicastPacket (Ptr<Socket> socket)
   416 {
   417   Ptr<Packet> packet;
   418   while (packet = socket->Recv ())
   419     {
   420       MultipartNetlinkMessage nlmsg;
   421       packet->RemoveHeader (nlmsg);
   422       m_unicastList.push_back (nlmsg);
   423     }
   424 }
   425 
   426 void
   427 NetlinkSocketTestCase::ReceiveMulticastPacket (Ptr<Socket> socket)
   428 {
   429   Ptr<Packet> packet;
   430   while (packet = socket->Recv ())
   431     {
   432       MultipartNetlinkMessage nlmsg;
   433       packet->RemoveHeader (nlmsg);
   434       m_multicastList.push_back (nlmsg);
   435     }
   436 }
   437 void
   438 NetlinkSocketTestCase::MonitorKernelChanges ()
   439 {
   440   NS_LOG_INFO ("At = " << Simulator::Now ().GetSeconds () << "s, group socket check the recv list");
   441 
   442   if (m_multicastList.size ())
   443     {
   444       MultipartNetlinkMessage multinlmsg = m_multicastList.front ();
   445 
   446       if (multinlmsg.GetNMessages () == 1)
   447         {
   448           NetlinkMessage nlmsg = multinlmsg.GetMessage (0);
   449           uint16_t type;
   450           type = nlmsg.GetMsgType ();
   451           NS_ASSERT (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR ||
   452                      type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE);
   453           NS_LOG_INFO ("group socket recv netlink message, type =" << type);          
   454         }
   455       else
   456         {
   457           NS_LOG_WARN ("group socket recv an unwanted message");
   458         }
   459       m_multicastList.pop_front ();
   460     }
   461 
   462   //restart this timer
   463   if (Simulator::Now ().GetSeconds () < 10)
   464     {
   465       Simulator::Schedule (Seconds (1), &NetlinkSocketTestCase::MonitorKernelChanges, this);
   466     }
   467 }
   468 
   469 
   470 
   471 NetlinkSocketTestCase::NetlinkSocketTestCase ()
   472   : TestCase ("Netlink"),
   473     m_pid(1) {}
   474 
   475 Ptr<SocketFactory>
   476 NetlinkSocketTestCase::CreateNetlinkFactory (void)
   477 {
   478   ObjectFactory factory;
   479   factory.SetTypeId ("ns3::NetlinkSocketFactory");
   480   return factory.Create<SocketFactory> ();
   481 }
   482 
   483 void
   484 NetlinkSocketTestCase::DoRun (void)
   485 {
   486   //init nodes with stacks and device
   487   // Network topology
   488   //
   489   //   n0
   490   //     \ 5 Mb/s, 2ms
   491   //      \          1.5Mb/s, 10ms
   492   //       n1 -------------------------n2
   493 
   494 
   495   NodeContainer nodes; 
   496   nodes.Create (3);
   497   NodeContainer n0n1 = NodeContainer (nodes.Get (0), nodes.Get (1));
   498   NodeContainer n1n2 = NodeContainer (nodes.Get (1), nodes.Get (2));
   499 
   500   InternetStackHelper stack;
   501   stack.Install (nodes);
   502 
   503   //add a p2p device with an ip address  
   504   PointToPointHelper p2p;  
   505   p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));  
   506   p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));  
   507   NetDeviceContainer d0d1 = p2p.Install (n0n1);
   508   p2p.SetDeviceAttribute ("DataRate", StringValue ("1.5Mbps"));
   509   p2p.SetChannelAttribute ("Delay", StringValue ("10ms"));
   510   NetDeviceContainer d1d2 = p2p.Install (n1n2);
   511 
   512   Ipv4AddressHelper ipv4;
   513   ipv4.SetBase ("10.1.1.0", "255.255.255.0");
   514   Ipv4InterfaceContainer i01 = ipv4.Assign (d0d1);
   515   ipv4.SetBase ("10.1.2.0", "255.255.255.0");
   516   Ipv4InterfaceContainer i12 = ipv4.Assign (d1d2);
   517 
   518   Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
   519 
   520   /*create two netlink sockets in node1 
   521   one is to exchange information between userspace and kernel ,
   522   one is to monitor the changes happened in kernel
   523   */
   524   Ptr<Node> node0 = nodes.Get (1);
   525   Ptr<SocketFactory> socketFactory = CreateNetlinkFactory();
   526   node0->AggregateObject (socketFactory);
   527   NetlinkSocketAddress addr;
   528 
   529   /*creat an cmd netlink socket, it send cmd to kernel space*/
   530   m_cmdSock = socketFactory->CreateSocket ();
   531   m_cmdSock->SetRecvCallback (MakeCallback (&NetlinkSocketTestCase::ReceiveUnicastPacket, this)); 
   532   addr.SetProcessID (m_pid);
   533   addr.SetGroupsMask (0);
   534   m_cmdSock->Bind (addr); 
   535 
   536   /*creat an group netlink socket, it monitor the kernel's changes*/
   537   m_groupSock = socketFactory->CreateSocket ();
   538   m_groupSock->SetRecvCallback (MakeCallback (&NetlinkSocketTestCase::ReceiveMulticastPacket, this)); 
   539   addr.SetProcessID (m_pid + 1);
   540   addr.SetGroupsMask (NETLINK_RTM_GRP_IPV4_IFADDR|NETLINK_RTM_GRP_IPV4_ROUTE);
   541   m_groupSock->Bind (addr); 
   542 
   543   /*test 1: for Serialize and Deserialize*/
   544   TestNetlinkSerialization ();
   545 
   546   /*test 2: for interface address dump/add/get message*/
   547   TestInterfaceAddressMessage ();
   548 
   549   /*test 3: for interface info dump message*/
   550   TestInferfaceInfoMessage ();
   551 
   552   /*test 4: for route dump/add/get message*/
   553   TestRouteMessage ();
   554 
   555   /*test 5: for netlink broadcast */
   556   TestBroadcastMessage ();
   557 
   558   Simulator::Run ();
   559 }
   560 
   561 static class NetlinkSocketTestSuite : public TestSuite
   562 {
   563 public:
   564   NetlinkSocketTestSuite ();
   565 private:
   566 } g_netlinkTestSuite;
   567 
   568 NetlinkSocketTestSuite::NetlinkSocketTestSuite ()
   569   : TestSuite ("netlink-socket", UNIT)
   570 {
   571   AddTestCase (new NetlinkSocketTestCase ());
   572 }
   573 
   574 } // namespace ns3
   575 
   576