--- a/model/netlink/netlink-socket.cc Mon Apr 18 09:01:30 2011 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1566 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2008 Liu Jian
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Liu Jian <liujatp@gmail.com>
- * Hajime Tazaki <tazaki@sfc.wide.ad.jp>
- */
-
-#include "netlink-socket.h"
-#include "netlink-socket-address.h"
-#include "netlink-message.h"
-#include "netlink-message-route.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/packet.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4.h"
-#include "ns3/simple-net-device.h"
-#include "ns3/uinteger.h"
-#include "ns3/trace-source-accessor.h"
-#include <iostream>
-#include <sstream>
-#include "ns3/ipv6-address.h"
-#include "ns3/ipv6.h"
-#include "ns3/ipv4-l3-protocol.h"
-#include "ns3/ipv4-static-routing-helper.h"
-#include "ns3/ipv4-routing-table-entry.h"
-#include "ns3/ipv6-l3-protocol.h"
-#include "ns3/ipv6-interface.h"
-#include "ns3/ipv6-static-routing-helper.h"
-#include "ns3/ipv6-routing-table-entry.h"
-#include "ns3/socket.h"
-#include "ns3/mac48-address.h"
-#include <sys/socket.h>
-#include <linux/if.h>
-#include <errno.h>
-
-NS_LOG_COMPONENT_DEFINE ("NetlinkSocket");
-
-namespace ns3 {
-
-// GroupSockets store the netlinksocket with noero group value
-// it was due to the mulitcast netlink messages.
-class GroupSockets
-{
-public:
- static uint32_t GetNSockets(void)
- {
- return m_Sockets.size();
- }
- static Ptr<NetlinkSocket> GetSocket(uint32_t index)
- {
- NS_ASSERT(index < m_Sockets.size());
- return m_Sockets[index];
- }
- static void AddSocket(Ptr<NetlinkSocket>sock)
- {
- m_Sockets.push_back(sock);
- }
-private:
- /*use a std::vector to store the sockets with nozero group value*/
- static std::vector<Ptr<NetlinkSocket> >m_Sockets;
-};
-std::vector<Ptr<NetlinkSocket> >GroupSockets::m_Sockets;
-
-NS_OBJECT_ENSURE_REGISTERED (NetlinkSocket);
-
-/*
-Netlink Socket
-*/
-TypeId
-NetlinkSocket::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::NetlinkSocket")
- .SetParent<Socket> ()
- .AddConstructor<NetlinkSocket> ()
- .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
- MakeTraceSourceAccessor (&NetlinkSocket::m_dropTrace))
- .AddAttribute ("RcvBufSize",
- "NetlinkSocket maximum receive buffer size (bytes)",
- UintegerValue (0xffffffffl),
- MakeUintegerAccessor (&NetlinkSocket::m_rcvBufSize),
- MakeUintegerChecker<uint32_t> ())
- .AddAttribute ("IcmpCallback", "Callback invoked whenever an icmp error is received on this socket.",
- CallbackValue (),
- MakeCallbackAccessor (&NetlinkSocket::m_icmpCallback),
- MakeCallbackChecker ())
- ;
- return tid;
-}
-
-NetlinkSocket::NetlinkSocket ()
- : m_shutdownSend (false),
- m_shutdownRecv (false),
- m_rxAvailable (0),
- m_srcPid (0),
- m_srcGroups (0),
- m_dstPid (0),
- m_dstGroups (0)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_errno = ERROR_NOTERROR;
-}
-NetlinkSocket::~NetlinkSocket ()
-{
- NS_LOG_FUNCTION (this);
-}
-void
-NetlinkSocket::DoDispose (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
-}
-
-int
-NetlinkSocket::ErrnoToSimuErrno (void)
-{
- switch (m_errno)
- {
- case Socket::ERROR_ISCONN:
- return EISCONN;
- case Socket::ERROR_NOTCONN:
- return ENOTCONN;
- case Socket::ERROR_MSGSIZE:
- return EMSGSIZE;
- case Socket::ERROR_AGAIN:
- return EAGAIN;
- case Socket::ERROR_SHUTDOWN:
- return ESHUTDOWN;
- case Socket::ERROR_OPNOTSUPP:
- return EOPNOTSUPP;
- case Socket::ERROR_AFNOSUPPORT:
- return EAFNOSUPPORT;
- case Socket::ERROR_INVAL:
- return EINVAL;
- case Socket::ERROR_BADF:
- return EBADF;
- case Socket::ERROR_NOROUTETOHOST:
- return EHOSTUNREACH;
- case Socket::ERROR_NODEV:
- return ENODEV;
- case Socket::ERROR_ADDRNOTAVAIL:
- return EADDRNOTAVAIL;
- case Socket::SOCKET_ERRNO_LAST:
- case Socket::ERROR_NOTERROR:
- default:
- NS_ASSERT (false);
- return 0; // quiet compiler
- break;
- }
-}
-
-void
-NetlinkSocket::SetNode (Ptr<Node> node)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_node = node;
-}
-
-
-enum Socket::SocketErrno
-NetlinkSocket::GetErrno (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_errno;
-}
-
-Ptr<Node>
-NetlinkSocket::GetNode (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_node;
-}
-
-uint32_t
-NetlinkSocket::GetSrcPid (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_srcPid;
-}
-uint32_t
-NetlinkSocket::GetSrcGroups (void)const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_srcGroups;
-}
-uint32_t
-NetlinkSocket::GetDstPid (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_dstPid;
-}
-uint32_t
-NetlinkSocket::GetDstGroups (void)const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_dstGroups;
-}
-
-int
-NetlinkSocket::Bind (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- NetlinkSocketAddress address;
- return DoBind (address);
-}
-int
-NetlinkSocket::Bind (const Address &address)
-{
- NS_LOG_FUNCTION (this << address);
-
- if (!NetlinkSocketAddress::IsMatchingType (address))
- {
- m_errno = ERROR_INVAL;
- return -1;
- }
- NetlinkSocketAddress ad = NetlinkSocketAddress::ConvertFrom (address);
- return DoBind (ad);
-}
-int
-NetlinkSocket::DoBind (const NetlinkSocketAddress &address)
-{
- NS_LOG_FUNCTION (this << address);
-
- m_srcPid = address.GetProcessID ();
- m_srcGroups = address.GetGroupsMask ();
-
- if (m_srcGroups)
- {
- GroupSockets::AddSocket(this);
- }
- return 0;
-}
-
-int
-NetlinkSocket::Listen (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_errno = Socket::ERROR_OPNOTSUPP;
- return -1;
-}
-
-uint32_t
-NetlinkSocket::GetTxAvailable (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return 0;
-}
-uint32_t
-NetlinkSocket::GetRxAvailable (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- // We separately maintain this state to avoid walking the queue
- // every time this might be called
- return m_rxAvailable;
-}
-
-int
-NetlinkSocket::ShutdownSend (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_shutdownSend = true;
- return 0;
-}
-int
-NetlinkSocket::ShutdownRecv (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- m_shutdownRecv = true;
- return 0;
-}
-
-int
-NetlinkSocket::Close (void)
-{
- NS_LOG_FUNCTION_NOARGS ();
- ShutdownSend();
- ShutdownRecv();
- return 0;
-}
-
-int
-NetlinkSocket::Connect (const Address &address)
-{
- NS_LOG_FUNCTION (this << address);
- m_errno = Socket::ERROR_OPNOTSUPP;
- return 0;
-}
-
-Ptr<Packet>
-NetlinkSocket::Recv (uint32_t maxSize, uint32_t flags)
-{
- NS_LOG_FUNCTION (this << maxSize<< flags);
- if (m_dataReceiveQueue.empty())
- {
- return 0;
- }
-
- Ptr<Packet> p = m_dataReceiveQueue.front ();
- if (p->GetSize () <= maxSize)
- {
- m_dataReceiveQueue.pop ();
- m_rxAvailable -= p->GetSize ();
- }
- else
- {
- p = 0;
- }
- return p;
-}
-
-Ptr<Packet>
-NetlinkSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
-{
- NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
- Ptr<Packet> packet = Recv (maxSize, flags);
- if (packet != 0)
- {
- SocketAddressTag tag;
- bool found;
- found = packet->FindFirstMatchingByteTag (tag);
- NS_ASSERT (found);
- fromAddress = tag.GetAddress ();
- }
- return packet;
-}
-
-int
-NetlinkSocket::Send (Ptr<Packet> p,uint32_t flags)
-{
- NS_LOG_FUNCTION (this << p << flags);
- NetlinkSocketAddress address = NetlinkSocketAddress(m_dstPid, m_dstGroups);
- return SendTo(p, flags, address);
-}
-
-int
-NetlinkSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &toAddress)
-{
- NS_LOG_FUNCTION (this << p << flags << toAddress);
- NetlinkSocketAddress ad;
-
- if (!NetlinkSocketAddress::IsMatchingType (toAddress))
- {
- NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
- m_errno = ERROR_AFNOSUPPORT;
- return -1;
- }
- ad = NetlinkSocketAddress::ConvertFrom (toAddress);
- m_dstPid = ad.GetProcessID();
- m_dstGroups = ad.GetGroupsMask();
- NS_LOG_INFO ("send netlink message to pid = " << m_dstPid << ", groups = " << m_dstGroups);
- NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Sending netlink message from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ());
-
- //Ptr<NetlinkSocket>kernel_socket = GetNetlinkSocketByAddress(ad);
- //kernel_socket->m_receivedData.push_back(p);
- //kernel_socket->NotifyDataReceived(p);
-
- //when netlink socket send packet, the first step is to find the dest netlink socket through address
- //then send the packet to it. For we partly implement the netlink-family, the dest address
- //is always the kernel(pid = 0), (Actually, there must be one static kernel netlink socket to
- //receive/handle messages), we do not setup a kernel socket to receive packet.
- //
-
- MultipartNetlinkMessage multipartnlmsg;
- uint32_t packet_len, remain_len;
-
- packet_len = p->GetSize ();
- remain_len = packet_len;
-
- while (remain_len > NetlinkMessageHeader::GetHeaderSize ())
- {
- remain_len -= p->RemoveHeader (multipartnlmsg);
- NS_ASSERT (remain_len == p->GetSize ());
-
- //actually, message to kernel contains single one netlink message
- for (uint32_t i = 0; i < multipartnlmsg.GetNMessages(); i ++)
- {
- NetlinkMessage nlmsg = multipartnlmsg.GetMessage (i);
- if (HandleMessage (nlmsg) < 0)
- {
- if (m_errno)
- {
- SendAckMessage (nlmsg, -ErrnoToSimuErrno ());
- }
- }
- else if (NetlinkMessage::IsMessageFlagsAck (nlmsg.GetHeader ().GetMsgFlags ()))
- {
- SendAckMessage (nlmsg, 0);
- }
- }
- }
-
- NotifyDataSent (packet_len);
- NS_LOG_INFO ("netlink socket kernel error " << -m_errno);
- return packet_len;
-}
-
-int
-NetlinkSocket::GetSockName (Address &address) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- NetlinkSocketAddress ad;
-
- ad.SetProcessID (GetSrcPid ());
- ad.SetGroupsMask (GetSrcGroups ());
- address = ad;
- return 0;
-}
-int
-NetlinkSocket::GetPeerName (Address &address) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- // XXX
- NS_ASSERT (false);
- return -1;
-}
-bool
-NetlinkSocket::SetAllowBroadcast (bool allowBroadcast)
-{
- NS_ASSERT (false);
- return false;
-}
-bool
-NetlinkSocket::GetAllowBroadcast () const
-{
- NS_ASSERT (false);
- return false;
-}
-
-
-void
-NetlinkSocket::ForwardUp (Ptr<Packet> packet, NetlinkSocketAddress &address)
-{
- NS_LOG_FUNCTION (this << packet << address);
-
- if (m_shutdownRecv)
- {
- return;
- }
- if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
- {
- SocketAddressTag tag;
- tag.SetAddress (address);
- packet->AddByteTag (tag);
- m_dataReceiveQueue.push (packet);
- m_rxAvailable += packet->GetSize ();
- NotifyDataRecv ();
- }
- else
- {
- NS_LOG_WARN ("No receive buffer space available. Drop.");
- m_dropTrace (packet);
- }
-}
-
-int32_t
-NetlinkSocket::SendMessageUnicast (const MultipartNetlinkMessage &nlmsg, uint32_t pid, int32_t nonblock)
-{
- NS_LOG_FUNCTION (this << pid << nonblock);
- //here we send message instantly
- Ptr<Packet> p = Create<Packet> ();
- p->AddHeader (nlmsg);
-
- NetlinkSocketAddress address;
- address.SetProcessID (pid);
-
- //send packet to user space
- ForwardUp (p, address);
- return 0;
-}
-int32_t
-NetlinkSocket::SendMessageBroadcast (const MultipartNetlinkMessage &nlmsg,
- uint32_t pid,
- uint32_t group,
- Ptr<Node> node)
-{
- NS_LOG_FUNCTION ("SendMessageBroadcast" << pid << group);
- //fisrt find the dest netlink socket through group value, then attach this nlmsg to its recv-queue
- for (uint32_t i = 0; i < GroupSockets::GetNSockets (); i ++)
- {
- Ptr<NetlinkSocket> nlsock = GroupSockets::GetSocket (i);
-
- if ((nlsock->GetSrcGroups () & group) &&
- (nlsock->GetSrcPid () != pid) &&
- node == nlsock->GetNode ())
- {
- //here we send message instantly
- Ptr<Packet> p = Create<Packet> ();
- p->AddHeader (nlmsg);
-
- NetlinkSocketAddress address;
- address.SetProcessID (nlsock->GetSrcPid());
- address.SetGroupsMask (group);
-
- //send packet to user space
- nlsock->ForwardUp (p, address);
- }
- }
- return 0;
-}
-void
-NetlinkSocket::SendAckMessage (const NetlinkMessage&nlmsg, int32_t err)
-{
- NS_LOG_FUNCTION (this << err);
- NetlinkMessageHeader rep;
- NetlinkMessage ackmsg;
- NetlinkMessageError errmsg;
-
- rep.SetMsgPid (nlmsg.GetHeader ().GetMsgPid ());
- rep.SetMsgSeq (nlmsg.GetHeader ().GetMsgSeq ());
- rep.SetMsgType (NETLINK_MSG_ERROR);
- rep.SetMsgFlags (0);
-
- errmsg.SetError (err);
- //kernel send the whole nlmsg back if error != 0, here we just send the header back
- errmsg.SetMsg (nlmsg.GetHeader ());
-
- //then send errmsg back to user space
- ackmsg.SetHeader (rep);
- ackmsg.SetErrorMessage (errmsg);
-
- SendMessageUnicast (ackmsg, rep.GetMsgPid (), 1);
-}
-
-int32_t
-NetlinkSocket::HandleMessage (const NetlinkMessage&nlmsg)
-{
- NS_LOG_FUNCTION (this);
- uint16_t type = nlmsg.GetMsgType ();
- NetlinkMessageHeader nhr = nlmsg.GetHeader ();
-
- if (nhr.GetMsgLen () < NetlinkMessageHeader::GetHeaderSize ())
- {
- m_errno = ERROR_INVAL;
- return -1;
- }
-
- if (NetlinkMessage::IsMessageNetlinkControl (type))
- {
- NS_LOG_INFO ("netlink control message type not parsed in kernel");
- return 0;
- }
- else if (NetlinkMessage::IsMessageNetlinkRoute (type))
- {
- return HandleNetlinkRouteMessage (nlmsg);
- }
- else
- {
- NS_LOG_INFO ("netlink message type not parsed in kernel");
- m_errno = ERROR_INVAL;
- return -1;
- }
-}
-
-int32_t
-NetlinkSocket::HandleNetlinkRouteMessage (const NetlinkMessage &nlmsg)
-{
- NS_LOG_FUNCTION (this);
- uint8_t family;
- int16_t type;
- int32_t err;
-
- /* Only requests are handled by kernel now */
- if (!NetlinkMessage::IsMessageFlagsRequest (nlmsg.GetHeader ().GetMsgFlags ()))
- return 0;
-
- type = nlmsg.GetMsgType ();
-
- /* A control message: ignore them */
- if (NetlinkMessage::IsMessageNetlinkControl (type))
- {
- return 0;
- }
- else if (NetlinkMessage::IsMessageNetlinkRoute (type))
- {
- /* All the messages must have at least 1 byte length */
- if (nlmsg.GetPayloadSize () < 1)
- return 0;
-
- family = nlmsg.GetFamily ();
- /*here we do not deal with different family, default for AF_NET*/
- NS_ASSERT(family == AF_INET || family == AF_UNSPEC || family == AF_PACKET || family == AF_INET6);
-
- /*for GET*** message, dump it to userspace*/
- if (NetlinkMessage::IsMessageTypeGet (type) &&
- NetlinkMessage::IsMessageFlagsDump (nlmsg.GetHeader ().GetMsgFlags ()))
- {
- DumpNetlinkRouteMessage (nlmsg, type, family);
- return -1;
- }
-
- /* other types of messages*/
- return DoNetlinkRouteMessage (nlmsg, type, family);
- }
- else/* Unknown message: reply with EINVAL */
- {
- err = ERROR_INVAL;
- return -1;
- }
-}
-
-int32_t
-NetlinkSocket::DumpNetlinkRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
-{
- NS_LOG_FUNCTION (this << type << family);
-
- NS_ASSERT (type == NETLINK_RTM_GETADDR || type == NETLINK_RTM_GETROUTE || type == NETLINK_RTM_GETLINK);
-
- MultipartNetlinkMessage nlmsg_dump;
- NetlinkMessageHeader nhr = nlmsg.GetHeader ();
- int32_t err;
-
- if (type == NETLINK_RTM_GETADDR)
- {
- nlmsg_dump = BuildInterfaceAddressDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);
- }
- else if (type == NETLINK_RTM_GETLINK)
- {
- nlmsg_dump = BuildInterfaceInfoDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);
- }
- else if (type == NETLINK_RTM_GETROUTE)
- {
- nlmsg_dump = BuildRouteDumpMessage (m_srcPid, nhr.GetMsgSeq(), family);
- }
- else
- {
- m_errno = ERROR_INVAL;
- return -1;
- }
-
- //then append netlink message with type NLMSG_DONE
- NetlinkMessage nlmsg_done;
- NetlinkMessageHeader nhr2 = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI,
- nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
- nlmsg_done.SetHeader (nhr2);
- //kernel append nlmsg_dump size to it, here we omit it
- nlmsg_dump.AppendMessage (nlmsg_done);
-
- err = SendMessageUnicast (nlmsg_dump, m_srcPid, 1);
- return err;
-}
-
-/*here only for ADD/DEL/GET*** types*/
-int32_t
-NetlinkSocket::DoNetlinkRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
-{
- NS_LOG_FUNCTION (this << type <<family);
- int32_t err;
-
- if (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR)
- {
- err = DoInterfaceAddressMessage (nlmsg, type, family);
- }
- else if (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE || type == NETLINK_RTM_GETROUTE)
- {
- err = DoRouteMessage (nlmsg, type, family);
- }
- else if (type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_SETLINK)
- {
- err = DoInterfaceInfoMessage (nlmsg, type, family);
- }
- else
- {
- NS_LOG_LOGIC ("netlink message:type( " << type << ") not processed by ns3 now." );
- m_errno = ERROR_INVAL;
- err = -1;
- }
-
- return err;
-}
-
-MultipartNetlinkMessage
-NetlinkSocket::BuildInterfaceAddressDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
-{
- NS_LOG_FUNCTION (this << pid << seq <<family);
- MultipartNetlinkMessage nlmsg_dump;
- Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
-
- for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i ++)
- {
- if (!ipv4->IsUp (i))
- continue;
-
- Ipv4Address addri = ipv4->GetAddress (i, 0).GetLocal ();
- Ipv4Mask maski = ipv4->GetAddress (i, 0).GetMask ();
- Ipv4Address bcast = ipv4->GetAddress (i, 0).GetBroadcast ();
-
- //here get the address mask length
- uint32_t mask = maski.Get ();
- uint8_t mask_len = 0;
- while (mask)
- {
- mask = mask << 1;
- mask_len ++;
- }
-
- //next fill the message body
- NetlinkMessage nlmsg_ifa;
- NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI, seq, pid);
- InterfaceAddressMessage ifamsg;
-
- ifamsg.SetInterfaceIndex (i);
- ifamsg.SetFamily (AF_INET);//default AF_INET
- ifamsg.SetLength (mask_len);
- ifamsg.SetFlags (0);
- ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
-
- ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL, ADDRESS, addri));
- ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS, ADDRESS, addri));
- ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_BROADCAST,ADDRESS, bcast));
- // ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL, STRING, "ns3-ifaddr"));//not used in ns3
- //ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ANYCAST, ADDRESS, Ipv4Address("0.0.0.0")));//not used in ns3
- //XXXother attributes not used by ns3
-
- nlmsg_ifa.SetHeader(nhr);
- nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
- nlmsg_dump.AppendMessage (nlmsg_ifa);
- }
-
- // For IPv6
- Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
-
- for (uint32_t i = 0; i < ipv6->GetNInterfaces(); i ++)
- {
- if (!ipv6->IsUp (i))
- continue;
-
- for (uint32_t j = 0; j < ipv6->GetNAddresses(i); j ++)
- {
- Ipv6Address addri = ipv6->GetAddress (i, j).GetAddress();
- Ipv6Prefix prefix = ipv6->GetAddress (i, j).GetPrefix ();
-
- //here get the address mask length
- uint8_t mask_len = prefix.GetPrefixLength();
-
- //loopback address's prefix is wrong... FIXME
- if (addri.IsEqual(Ipv6Address::GetLoopback()))
- mask_len = 128;
-
- //next fill the message body
- NetlinkMessage nlmsg_ifa;
- NetlinkMessageHeader nhr = NetlinkMessageHeader(NETLINK_RTM_NEWADDR, NETLINK_MSG_F_MULTI, seq, pid);
- InterfaceAddressMessage ifamsg;
-
- ifamsg.SetInterfaceIndex(i);
- ifamsg.SetFamily(AF_INET6);
- ifamsg.SetFlags(0);
-
-
- if (addri.IsLinkLocal())
- {
- ifamsg.SetLength(64);
- ifamsg.SetScope (RouteMessage::RT_SCOPE_LINK);
- }
- else
- {
- ifamsg.SetLength(mask_len);
- ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
- }
-
-
- ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL, ADDRESS, addri));
- ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS, ADDRESS, addri));
- //XXXother attributes not used by ns3
-
- nlmsg_ifa.SetHeader(nhr);
- nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
- nlmsg_dump.AppendMessage (nlmsg_ifa);
- }
- }
- return nlmsg_dump;
-}
-MultipartNetlinkMessage
-NetlinkSocket::BuildInterfaceInfoDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
-{
- NS_LOG_FUNCTION (this << pid << seq <<family);
- MultipartNetlinkMessage nlmsg_dump;
- for (uint32_t i = 0; i < m_node->GetNDevices (); i ++)
- {
- Ptr<NetDevice> dev = m_node->GetDevice (i);
- Address mac;
- Address bcast;
- uint32_t mtu;
- uint32_t flags = 0;
-
- mac = dev->GetAddress ();
- bcast = dev->GetBroadcast ();
- mtu = (uint32_t)dev->GetMtu ();
-
- if (dev->IsLinkUp ())
- {
- flags |= IFF_RUNNING;
- flags |= IFF_UP;
- }
- if (dev->IsBroadcast ())
- {
- flags |= IFF_BROADCAST;
- }
- if (dev->IsMulticast ())
- {
- flags |= IFF_MULTICAST;
- }
-
- NetlinkMessage nlmsg_ifinfo;
- NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWLINK, NETLINK_MSG_F_MULTI, seq, pid);
- InterfaceInfoMessage ifinfomsg;
-
- ifinfomsg.SetFamily(0); // AF_UNSPEC
- ifinfomsg.SetDeviceType (0); // not clear
- ifinfomsg.SetInterfaceIndex (i);
- ifinfomsg.SetDeviceFlags (flags); // not clear
- ifinfomsg.SetChangeMask (0xffffffff);
-
- // the ns3 device have no name, here we set "ns3-device i" for test
- std::stringstream ss;
- ss << "ns3-device" << i;
-
- ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_IFNAME, STRING, ss.str()));
- //not used in ns3
- //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_TXQLEN, U32, 0));
- //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_WEIGHT, U32, 0));
- //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_OPERSTATE, U8, 0));
- //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_LINKMODE, U8, 0));
- //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MAP, UNSPEC, 0));
- ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_ADDRESS, ADDRESS, mac));
- ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_BROADCAST, ADDRESS, bcast));
- ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MTU, U32, mtu));
- ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_LINK, U32, i));
- //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_QDISC, STRING, ""));
- //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_MASTER, U32, 0));
- //ifinfomsg.AppendAttribute (NetlinkAttribute (InterfaceInfoMessage::IFL_A_STATS, UNSPEC, 0));
-
- nlmsg_ifinfo.SetHeader (nhr);
- nlmsg_ifinfo.SetInterfaceInfoMessage (ifinfomsg);
- nlmsg_dump.AppendMessage (nlmsg_ifinfo);
- }
- return nlmsg_dump;
-}
-MultipartNetlinkMessage
-NetlinkSocket::BuildRouteDumpMessage (uint32_t pid, uint32_t seq, uint8_t family)
-{
- NS_LOG_FUNCTION (this << pid << seq <<family);
- MultipartNetlinkMessage nlmsg_dump;
- Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
-
- // We only care about staticRouting for netlink support
- Ipv4StaticRoutingHelper routingHelper;
- Ptr<Ipv4StaticRouting> ipv4Static = routingHelper.GetStaticRouting (ipv4);
- for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
- {
- NetlinkMessage nlmsg_rt;
- NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
- RouteMessage rtmsg;
- Ipv4RoutingTableEntry route = ipv4Static->GetRoute (i);
-
- rtmsg.SetFamily (AF_INET);
- rtmsg.SetDstLength (32);
- rtmsg.SetSrcLength (0);
- rtmsg.SetTos (0);//not clear
- rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
- rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
- rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
- rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
-
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
- // ns3 use local address as the route src address
- // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, route.GetSource()));
- // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, route.GetSource()));//not used in ns3
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
-
- nlmsg_rt.SetHeader (nhr);
- nlmsg_rt.SetRouteMessage (rtmsg);
- nlmsg_dump.AppendMessage (nlmsg_rt);
- }
-
- Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
- // We only care about staticRouting for netlink support
- Ipv6StaticRoutingHelper routingHelper6;
- Ptr<Ipv6StaticRouting> ipv6Static = routingHelper6.GetStaticRouting (ipv6);
- for (uint32_t i = 0; i < ipv6Static->GetNRoutes (); i ++)
- {
- NetlinkMessage nlmsg_rt;
- NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, NETLINK_MSG_F_MULTI, seq, pid);
- RouteMessage rtmsg;
- Ipv6RoutingTableEntry route = ipv6Static->GetRoute (i);
-
- rtmsg.SetFamily (AF_INET6);
- rtmsg.SetDstLength (128);
- rtmsg.SetSrcLength (0);
- rtmsg.SetTos (0);//not clear
- rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
- rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
- rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
- rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
-
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
- //ns3 use local address as the route src address
- // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS,
- // ipv6->GetSourceAddress(route.GetDest ())));
- // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS,
- // ipv6->GetSourceAddress(route.GetDest ())));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface()));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface()));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway()));
-
- nlmsg_rt.SetHeader (nhr);
- nlmsg_rt.SetRouteMessage (rtmsg);
- nlmsg_dump.AppendMessage (nlmsg_rt);
- }
-
- return nlmsg_dump;
-}
-
-int32_t
-NetlinkSocket::DoInterfaceAddressMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
-{
- NS_LOG_FUNCTION (this << type << family);
- NS_ASSERT (type == NETLINK_RTM_NEWADDR || type == NETLINK_RTM_DELADDR);
-
- // XXX
- NS_ASSERT_MSG (false, "Not implemented yet (RTM_NEWADDR/RTM_DELADDR)");
-
- InterfaceAddressMessage ifamsg = nlmsg.GetInterfaceAddressMessage ();
- Ipv4Address addri, addr_local, bcast;
- NetlinkAttribute attr_local;
- uint32_t index = ifamsg.GetInterfaceIndex ();
- Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
- int flag4 = 0, flag6 = 0;
-
- if (type == NETLINK_RTM_NEWADDR)
- {
- //when adding an interface address, it should check the input arguments
- //prefix-len and local address attribute
- if (ifamsg.GetLength () > 32 ||
- ifamsg.GetAttributeByType (attr_local, InterfaceAddressMessage::IF_A_LOCAL) == false)
- {
- m_errno = ERROR_INVAL;
- return -1;
- }
- }
-
- //get necessary information for add/del, many attributes we not used
- for (uint32_t i = 0; i < ifamsg.GetNNetlinkAttribute (); i ++)
- {
- NetlinkAttribute attr = ifamsg.GetNetlinkAttribute (i);
- uint32_t attr_type = attr.GetAttrType ();
-
- switch(attr_type)
- {
- case InterfaceAddressMessage::IF_A_ADDRESS:
- addri = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
- break;
- case InterfaceAddressMessage::IF_A_BROADCAST:
- bcast = Ipv4Address::ConvertFrom(attr.GetAttrPayload ().GetAddress ());
- break;
- case InterfaceAddressMessage::IF_A_LOCAL:
- addr_local = Ipv4Address::ConvertFrom(attr.GetAttrPayload ().GetAddress ());
- break;
- case InterfaceAddressMessage::IF_A_LABEL:
- case InterfaceAddressMessage::IF_A_ANYCAST:
- break;
- }
- }
-
- if (type == NETLINK_RTM_NEWADDR)
- {
- //when adding an interface address by index, if the indexed interface was not exist,
- //create an new NetDevice with an new index and set the address
- //otherwise set the indexed interface directly
- if (index >= ipv4->GetNInterfaces ())
- {
- Ptr<SimpleNetDevice> dev;
- dev = CreateObject<SimpleNetDevice> ();
- dev ->SetAddress (Mac48Address::Allocate ());
- m_node->AddDevice (dev);
-
- uint32_t netdev_idx = ipv4->AddInterface (dev);
- // FIXME!
- Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addri, Ipv4Mask ());
- ipv4->AddAddress (netdev_idx, ipv4Addr);
- ipv4->SetUp (netdev_idx);
- NS_LOG_INFO ("Add an interface address at index "<< netdev_idx << "but not the ifamsg input" << index);
- }
- else
- {
- Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (addri, Ipv4Mask ());
- ipv4->AddAddress (index, ipv4Addr);
- if (!ipv4->IsUp (index))
- ipv4->SetUp (index);
- }
- flag4 = 1;
- }
- else//type == NETLINK_RTM_DELADDR
- {
- //when delete an interface address by index, if the indexed interface was not exist
- //return an error EINVAL, otherwise set down the interface which has the addri
- if (index >= ipv4->GetNInterfaces ())
- {
- m_errno = ERROR_NODEV;
- return -1;
- }
- else
- {
- for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i ++)
- {
- Ipv4Address ad = ipv4->GetAddress (i, 0).GetLocal ();
- if (ad == addri && ipv4->IsUp (i))
- {
- ipv4->SetDown (i);
- break;
- }
- if (i == ipv4->GetNInterfaces () - 1)
- {
- m_errno = ERROR_ADDRNOTAVAIL;
- return -1;
- }
- }
- flag4 = 1;
- }
- }
-
- //then send an broadcast message, let all user know this operation happened
- NetlinkMessage nlmsg_broadcast = nlmsg;
- NetlinkMessageHeader nhr;
- nhr.SetMsgLen (nlmsg.GetHeader ().GetMsgLen ());
- nhr.SetMsgType (nlmsg.GetHeader ().GetMsgType ());
- nlmsg_broadcast.SetHeader (nhr);
- if (flag4)
- {
- SendMessageBroadcast (nlmsg_broadcast, 0, NETLINK_RTM_GRP_IPV4_IFADDR, GetNode ());
- }
- else if (flag6)
- {
- SendMessageBroadcast (nlmsg_broadcast, 0, RTMGRP_IPV6_IFADDR, GetNode ());
- }
-
- return 0;
-}
-
-int32_t
-NetlinkSocket::DoInterfaceInfoMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
-{
- NS_LOG_FUNCTION (this << type << family);
- NS_ASSERT (type == NETLINK_RTM_GETLINK || type == NETLINK_RTM_SETLINK);
- InterfaceInfoMessage ifinfomsg = nlmsg.GetInterfaceInfoMessage ();
- // XXX
- NS_ASSERT_MSG (false, "Not implemented yet (RTM_GETLINK/RTM_SETLINK)");
- return -1;
-}
-
-Address
-NetlinkSocket::ConvertFrom (uint8_t family, const Address &address)
-{
- Address retval;
- if (family == AF_INET)
- {
- retval = Ipv4Address::ConvertFrom (address);
- }
- else if (family == AF_INET6)
- {
- retval = Ipv6Address::ConvertFrom (address);
- }
- return retval;
-}
-
-int32_t
-NetlinkSocket::DoRouteMessage (const NetlinkMessage &nlmsg, uint16_t type, uint8_t family)
-{
- NS_LOG_FUNCTION (this << type << family);
- NS_ASSERT (type == NETLINK_RTM_NEWROUTE || type == NETLINK_RTM_DELROUTE ||type == NETLINK_RTM_GETROUTE);
-
- RouteMessage rtmsg = nlmsg.GetRouteMessage ();
- Ipv4Address src, dest, gateway;
- Ipv6Address src6, dest6, gateway6;
- uint32_t index = 0;
- int attr_flags[RouteMessage::RT_A_MAX] = {0};
- uint8_t dstlen = rtmsg.GetDstLength ();
-
- //get necessary information for add/del, many attributes we not used
- for (uint32_t i = 0; i < rtmsg.GetNNetlinkAttribute (); i ++)
- {
- NetlinkAttribute attr = rtmsg.GetNetlinkAttribute (i);
- uint32_t attr_type = attr.GetAttrType ();
- attr_flags[attr_type] = 1;
-
- switch(attr_type)
- {
- case RouteMessage::RT_A_DST:
- if (family == AF_INET)
- {
- dest = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
- }
- else if (family == AF_INET6)
- {
- dest6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
- }
- break;
- case RouteMessage::RT_A_SRC:
- if (family == AF_INET)
- {
- src = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
- }
- else if (family == AF_INET6)
- {
- src6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
- }
- break;
- case RouteMessage::RT_A_OIF:
- index = attr.GetAttrPayload ().GetU32 ();
- break;
- case RouteMessage::RT_A_GATEWAY:
- if (family == AF_INET)
- {
- gateway = Ipv4Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
- }
- else if (family == AF_INET6)
- {
- gateway6 = Ipv6Address::ConvertFrom (attr.GetAttrPayload ().GetAddress ());
- }
- break;
- case RouteMessage::RT_A_IIF:
- case RouteMessage::RT_A_PRIORITY:
- case RouteMessage::RT_A_PREFSRC:
- case RouteMessage::RT_A_METRICS:
- case RouteMessage::RT_A_MULTIPATH:
- case RouteMessage::RT_A_PROTOINFO:
- case RouteMessage::RT_A_FLOW:
- case RouteMessage::RT_A_CACHEINFO:
- case RouteMessage::RT_A_SESSION:
- case RouteMessage::RT_A_MP_ALGO:
- case RouteMessage::RT_A_TABLE:
- NS_LOG_INFO("route attribute not used by ns3" << attr_type);
- //not used by ns3
- break;
- }
- }
-
- // Sigh....
- Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
- Ipv4StaticRoutingHelper routingHelper;
- Ptr<Ipv4StaticRouting> ipv4Static = routingHelper.GetStaticRouting (ipv4);
-
- Ptr<Ipv6>ipv6 = m_node->GetObject<Ipv6> ();
- Ipv6StaticRoutingHelper routingHelper6;
- Ptr<Ipv6StaticRouting> ipv6Static = routingHelper6.GetStaticRouting (ipv6);
-
- NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " Route message, type: " << type << "; from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
- << " to " << dest<< " through " << gateway);
-
- if (type == NETLINK_RTM_NEWROUTE)
- {
- //ns3 add a route entry only depends on 2 or 3 attribute
- //other route msg attibute were ignored
- if (attr_flags[RouteMessage::RT_A_DST])
- {
- if (family == AF_INET)
- {
- if (!attr_flags[RouteMessage::RT_A_OIF])
- {
- bool found = 0;
- for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++)
- {
- for (uint32_t j = 0; j < ipv4->GetNAddresses (i); j++)
- {
- if ((attr_flags[RouteMessage::RT_A_GATEWAY]))
- {
- Ipv4Mask mask = ipv4->GetAddress (i, j).GetMask ();
- if (mask.IsMatch (ipv4->GetAddress (i, j).GetLocal (), gateway))
- {
- index = i;
- found = true;
- break;
- }
- }
- if (found) break;
- }
- }
- if (!found)
- {
- NS_LOG_DEBUG ("No suitable interface to add an route entry");
- m_errno = ERROR_ADDRNOTAVAIL;
- return -1;
- }
- }
- if (dstlen == 32)
- {
- int exist_flag = 0;
- for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
- {
- Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
- if (dest == rt.GetDest ())
- {
- exist_flag = 1;
- }
- }
-
- if (exist_flag)
- { //route to dest already exists
- int delete_flag = 0;
- if (nlmsg.GetHeader ().GetMsgFlags () & NETLINK_MSG_F_REPLACE)
- {
- for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
- {
- Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
- if (dest == rt.GetDest ())
- {
- ipv4Static->RemoveRoute (i);
- NS_LOG_DEBUG ("Route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to "
- << dest << " through " << gateway << " removed");
- delete_flag = 1;
- }
- }
-
- if (!delete_flag)
- {
- NS_LOG_INFO ("no route entry removed by dest address in new route sector " << dest);
- m_errno = ERROR_INVAL;
- return -1;
- }
- }
- else
- {
- NS_LOG_DEBUG ("Route exists but overwriting declined!");
- }
- if ((attr_flags[RouteMessage::RT_A_GATEWAY]))
- {
- NS_LOG_DEBUG (Simulator::Now().GetSeconds() << "Overwrite route from "
- << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to " << dest<< " through " << gateway << " with index" << index);
- ipv4Static->AddHostRouteTo (dest, gateway, index);
- }
- else
- {
- NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Overwrite route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
- << " to " << dest<< " through " << "self" << " with index" << index);
- ipv4Static->AddHostRouteTo (dest, index);
- }
- }
- else
- { //route to dest doesn't exist
- if (nlmsg.GetHeader ().GetMsgFlags () & NETLINK_MSG_F_CREATE)
- {
- if (attr_flags[RouteMessage::RT_A_GATEWAY])
- {
- NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Add new route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
- << " to " << dest<< " through " << gateway << " with index" << index);
- ipv4Static->AddHostRouteTo (dest, gateway, index);
- }
- else
- {
- NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Add new route from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
- << " to " << dest<< " through " << "self" << " with index" << index);
- ipv4Static->AddHostRouteTo (dest, index);
- }
- }
- else
- {
- NS_LOG_ERROR ("Route doesn't exist but writing declined!");
- }
- }
-
- NS_LOG_DEBUG ("=After change attempt=");
- //Dump of table
- NS_LOG_DEBUG (m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << ":");
- for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); ++i)
- {
- Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
- NS_LOG_DEBUG (rt.GetDest () << " through " << rt.GetGateway ());
- }
- NS_LOG_DEBUG ("= = = = = = = = = = =");
- }
- else // dstlen != 32
- {
- if (attr_flags[RouteMessage::RT_A_GATEWAY])
- {
- ipv4Static->AddNetworkRouteTo (dest, Ipv4Mask (~(1<<(32 - dstlen))+1), gateway, index);
- }
- else
- {
- ipv4Static->AddNetworkRouteTo (dest, Ipv4Mask (~(1<<(32 - dstlen))+1), index);
- }
- }
- }
- else if (family == AF_INET6)
- {
- if (!attr_flags[RouteMessage::RT_A_OIF])
- {
-#ifdef FIXME
- if (ipv6->GetIfIndexForDestination (gateway6, index) == false)
- {
- NS_LOG_INFO ("No suitable interface to add an route entry");
- m_errno = ERROR_ADDRNOTAVAIL;
- return -1;
- }
-#endif
- }
-
- Ipv6Prefix pref (dstlen);
- if (attr_flags[RouteMessage::RT_A_GATEWAY])
- {
- ipv6Static->AddNetworkRouteTo (dest6, pref, gateway6, index);
- }
- else
- {
- ipv6Static->AddNetworkRouteTo (dest6, pref, Ipv6Address("::"), index);
- }
- }
- }
- else
- {
- NS_LOG_INFO("too few attributes to add an route entry");
- m_errno = ERROR_INVAL;
- return -1;
- }
- }
- else if (type == NETLINK_RTM_DELROUTE)
- {
- NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "Route delete request from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ()
- << " to " << dest<< " through " << gateway);
- if (attr_flags[RouteMessage::RT_A_DST])
- {
- int delete_flag = 0;
-
- if (family == AF_INET)
- {
- for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
- {
- Ipv4RoutingTableEntry rt = ipv4Static->GetRoute (i);
- if (gateway == rt.GetGateway () && dest == rt.GetDest ())
- {
- ipv4Static->RemoveRoute (i);
- delete_flag = 1;
- }
- }
- }
- else if (family == AF_INET6)
- {
- for (uint32_t i = 0; i < ipv6Static->GetNRoutes (); i ++)
- {
- Ipv6RoutingTableEntry rt = ipv6Static->GetRoute (i);
- if (gateway6 == rt.GetGateway () && dest6 == rt.GetDest ())
- {
- ipv6Static->RemoveRoute (i);
- delete_flag = 1;
- }
- }
- }
-
- if (!delete_flag)
- {
- NS_LOG_INFO ("no route entry removed by dest address " << dest);
- m_errno = ERROR_INVAL;
- return -1;
- }
- }
- else
- {
- NS_LOG_INFO ("too few attributes to add an route entry");
- m_errno = ERROR_INVAL;
- return -1;
- }
- }
- else// type == NETLINK_RTM_GETROUTE
- {
- NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "GetRoute "<< "from " << m_node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal () << " to " << dest);
- if (!attr_flags[RouteMessage::RT_A_DST])
- {
- NS_LOG_INFO ("too few attributes to get an route entry");
- m_errno = ERROR_INVAL;
- return -1;
- }
-
- int get_flag = 0;
- if (family == AF_INET)
- {
- for (uint32_t i = 0; i < ipv4Static->GetNRoutes (); i ++)
- {
- Ipv4RoutingTableEntry route = ipv4Static->GetRoute (i);
- //find the route entry with same dest address and send unicast to user space
- if (dest.IsEqual (route.GetDest ()))
- {
- // Ptr<Ipv4>ipv4 = m_node->GetObject<Ipv4> ();
- NetlinkMessage nlmsg_route;
- NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, 0,
- nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
- RouteMessage rtmsg;
-
- //fill rtmsg and attributes
- rtmsg.SetFamily (AF_INET);
- rtmsg.SetDstLength (32);
- rtmsg.SetSrcLength (0);
- rtmsg.SetTos (0);//not clear
- rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
- rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
- rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
- rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
-
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
- //ns3 use local address as the route src address
- // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv4->GetSourceAddress(route.GetDest ())));
- // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv4->GetSourceAddress(route.GetDest ())));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
-
- //fill an netlink message body
- nlmsg_route.SetHeader (nhr);
- nlmsg_route.SetRouteMessage (rtmsg);
-
- SendMessageUnicast (nlmsg_route, m_srcPid, 1);
- get_flag = 1;
- }
- }
- }
- else if (family == AF_INET6)
- {
- for (uint32_t i = 0; i < ipv6Static->GetNRoutes(); i ++)
- {
- Ipv6RoutingTableEntry route = ipv6Static->GetRoute (i);
- //find the route entry with same dest address and send unicast to user space
- if (dest6.IsEqual (route.GetDest ()))
- {
- NetlinkMessage nlmsg_route;
- NetlinkMessageHeader nhr = NetlinkMessageHeader (NETLINK_RTM_NEWROUTE, 0,
- nlmsg.GetHeader ().GetMsgSeq (), m_srcPid);
- RouteMessage rtmsg;
-
- //fill rtmsg and attributes
- rtmsg.SetFamily (AF_INET6);
- rtmsg.SetDstLength (32);
- rtmsg.SetSrcLength (0);
- rtmsg.SetTos (0);//not clear
- rtmsg.SetTableId (RouteMessage::RT_TABLE_MAIN);
- rtmsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
- rtmsg.SetProtocol (RouteMessage::RT_PROT_UNSPEC);
- rtmsg.SetFlags (RouteMessage::RT_F_CLONED);
-
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_DST, ADDRESS, route.GetDest ()));
- //ns3 use local address as the route src address
- // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_SRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
- // rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_PREFSRC, ADDRESS, ipv6->GetSourceAddress(route.GetDest ())));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_IIF, U32, route.GetInterface ()));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_OIF, U32, route.GetInterface ()));
- rtmsg.AppendAttribute (NetlinkAttribute (RouteMessage::RT_A_GATEWAY, ADDRESS, route.GetGateway ()));
-
- //fill an netlink message body
- nlmsg_route.SetHeader (nhr);
- nlmsg_route.SetRouteMessage (rtmsg);
-
- SendMessageUnicast (nlmsg_route, m_srcPid, 1);
- get_flag = 1;
- }
- }
- }
-
- if (!get_flag)
- {
- NS_LOG_INFO ("no route entry exist by dest address" << dest);
- m_errno = ERROR_INVAL;
- return -1;
- }
- }
-
- //then send an broadcast message, let all user know this operation happened
- MultipartNetlinkMessage nlmsg_multi;
- NetlinkMessage nlmsg_broadcast = nlmsg;
- NetlinkMessage nlmsg_done;
- NetlinkMessageHeader nhr_done = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 0, 0);
- nlmsg_done.SetHeader (nhr_done);
- nlmsg_multi.AppendMessage (nlmsg);
- nlmsg_multi.AppendMessage (nlmsg_done);
- SendMessageBroadcast (nlmsg_multi, 0, NETLINK_RTM_GRP_IPV4_ROUTE, GetNode ());
- // SendMessageBroadcast(nlmsg_broadcast, 0, RTMGRP_IPV6_ROUTE);
- return 0;
-}
-
-int32_t
-NetlinkSocket::NotifyIfLinkMessage (Address address, uint16_t type, uint8_t family)
-{
- NS_ASSERT_MSG (false, "Not implemented yet (NotifyIfLinkMessage)");
- return 0;
-}
-
-int32_t
-NetlinkSocket::NotifyIfAddrMessage (Ipv6Interface* interface, Ipv6Address addr, int cmd)
-{
- MultipartNetlinkMessage nlmsg_multi;
- NetlinkMessage nlmsg_ifa;
- NetlinkMessageHeader nhr = NetlinkMessageHeader (cmd, NETLINK_MSG_F_MULTI, 0, 0);
- InterfaceAddressMessage ifamsg;
-
- NS_ASSERT_MSG (false, "Not implemented yet (NotifyIfAddrMessage)");
-
- // FIXME!
- Ipv6Prefix prefix = Ipv6Prefix(64);
-
- //here get the address mask length
- uint8_t bytes[16];
- prefix.GetBytes (bytes);
- uint8_t mask_len = 0;
- for (int j = 0; j < 16; j++)
- {
- while (bytes[j])
- {
- bytes[j] = bytes[j] << 1;
- mask_len ++;
- }
- }
-
- ifamsg.SetInterfaceIndex (interface->GetDevice ()->GetIfIndex ());
- ifamsg.SetFamily (AF_INET6);
- ifamsg.SetLength (mask_len);
- ifamsg.SetFlags (0);
- ifamsg.SetScope (RouteMessage::RT_SCOPE_UNIVERSE);
-
- ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LOCAL, ADDRESS, addr));
- ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ADDRESS, ADDRESS, addr));
- // ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_BROADCAST,ADDRESS, bcast));
- // ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_LABEL, STRING, "ns3-ifaddr"));//not used in ns3
- //ifamsg.AppendAttribute (NetlinkAttribute (InterfaceAddressMessage::IF_A_ANYCAST, ADDRESS, Ipv4Address("0.0.0.0")));//not used in ns3
- //XXXother attributes not used by ns3
-
- nlmsg_ifa.SetHeader (nhr);
- nlmsg_ifa.SetInterfaceAddressMessage (ifamsg);
-
- NetlinkMessage nlmsg_done;
- NetlinkMessageHeader nhr_done = NetlinkMessageHeader (NETLINK_MSG_DONE, NETLINK_MSG_F_MULTI, 0, 0);
- nlmsg_done.SetHeader (nhr_done);
-
- nlmsg_multi.AppendMessage (nlmsg_ifa);
- nlmsg_multi.AppendMessage (nlmsg_done);
-
- SendMessageBroadcast (nlmsg_multi, 0, RTMGRP_IPV6_IFADDR, interface->GetDevice ()->GetNode ());
- return 0;
-}
-
-#ifdef FIXME
-int32_t
-NetlinkSocket::NotifyRouteMessage(Ojbect route, uint16_t type, uint8_t family)
-{
- NetlinkMessage nlmsg_broadcast = nlmsg;
- NetlinkMessageHeader nhr;
- NS_ASSERT_MSG (false, "Not implemented yet");
-
- nhr.SetMsgLen (nlmsg.GetHeader ().GetMsgLen ());
- nhr.SetMsgType (nlmsg.GetHeader ().GetMsgType ());
- nlmsg_broadcast.SetHeader (nhr);
- SendMessageBroadcast (nlmsg_broadcast, 0, RTMGRP_IPV6_ROUTE);
- return 0;
-}
-#endif
-
-}//namespace ns3