// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
//
// Copyright (c) 2008 University of Washington
//
// 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
//

#include "ns3/names.h"
#include "ns3/node.h"
#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/object.h"
#include "ns3/packet.h"
#include "ns3/net-device.h"
#include "ns3/ipv4-route.h"
#include "ipv4-global-routing-unordered-nexthops.h"

#include <iomanip>

NS_LOG_COMPONENT_DEFINE ("Ipv4GlobalRoutingUnorderedNexthops");

namespace ns3 {

NS_OBJECT_ENSURE_REGISTERED (Ipv4GlobalRoutingUnorderedNexthops);

TypeId 
Ipv4GlobalRoutingUnorderedNexthops::GetTypeId (void)
{ 
  static TypeId tid = TypeId ("ns3::Ipv4GlobalRoutingUnorderedNexthops")
    .SetParent<Ipv4GlobalRouting> ()
    .AddConstructor<Ipv4GlobalRoutingUnorderedNexthops> ()
  ;
  return tid;
}

Ipv4GlobalRoutingUnorderedNexthops::Ipv4GlobalRoutingUnorderedNexthops ()
: m_numLogicalEntries (1)
{
}

void
Ipv4GlobalRoutingUnorderedNexthops::FixRoutes ()
{
  for (Ipv4AddressTrieMap::iterator route = m_routes.begin ();
       route != m_routes.end ();
       route ++)
    {
      if (route->second->size () < m_numLogicalEntries)
        {
          NS_LOG_WARN ("Not all entries got a new routing entry. Making one based on previous set");
          route->second->push_back (route->second->back ());
          route->second->back ().SetMetric (UINT32_MAX); // just to ensure we have consistency across the sets
        }
    }
  m_numLogicalEntries ++;
}

void
Ipv4GlobalRoutingUnorderedNexthops::AddRouteTo (Ipv4Address dest, 
                                                Ipv4Mask destMask, 
                                                Ipv4Address nextHop, 
                                                uint32_t interface,
                                                uint32_t metric/*=0*/)
{
  NS_LOG_FUNCTION (dest << destMask << nextHop << interface << metric);
  
  // First, make sure we don't try to add route to ourselves
  int32_t iface = m_ipv4->GetInterfaceForPrefix (dest, destMask);
  NS_LOG_LOGIC ("Iface " << iface << " for " << dest);
  if (destMask != Ipv4Mask::GetZero () && iface >= 0)
    {
      NS_LOG_LOGIC ("Do not add route to ourselves");
      return;
    }

  // Second, there is no reason to add p2p route that equals to the next hop
  if (destMask == Ipv4Mask::GetOnes () && dest == nextHop)
    {
      NS_LOG_LOGIC ("Ignore route to nexthop via nexhop");
      return;
    }

  Ptr<EntryContainer> nextHops = 0;
  
  Ipv4AddressTrieMap::iterator route =
    m_routes.find (dest.CombineMask (destMask));
  if (route == m_routes.end ())
    {
      nextHops = Create<EntryContainer> ();
      m_routes[dest.CombineMask (destMask)] = nextHops;
    }
  else
    {
      nextHops = route->second;
    }

  // NS_LOG_ERROR ("numLogicalEntries: " << m_numLogicalEntries << ", nextHops->size: " << nextHops->size ());
  NS_ASSERT_MSG (nextHops->size ()==m_numLogicalEntries ||
                 nextHops->size ()==m_numLogicalEntries-1,
                 "Number of entries in nextHops should be either equal to number of logical entries, or one smaller");

  if (nextHops->size ()==m_numLogicalEntries-1)
    {
      // new entry
      nextHops->push_back (Ipv4RoutingTableEntry::CreateNetworkRouteTo (dest, destMask, nextHop, interface, metric));
    }
  else
    {
      if (nextHops->back ().GetMetric () > metric)
        {
          // update entry if new metric is smaller
          nextHops->back () = Ipv4RoutingTableEntry::CreateNetworkRouteTo (dest, destMask, nextHop, interface, metric);
        }
    }
}

Ptr<Ipv4Route>
Ipv4GlobalRoutingUnorderedNexthops::LookupGlobal (uint32_t entryNum, Ipv4Address dest, Ptr<NetDevice> oif)
{
  NS_LOG_FUNCTION_NOARGS ();
  NS_LOG_LOGIC ("Looking for route for destination " << dest);

  NS_ASSERT_MSG (m_numLogicalEntries > 0,
    "Number of logical entries should be at least one");

  NS_ASSERT_MSG (entryNum < m_numLogicalEntries,
               "Number of requested logical entry should be smaller than total number of logical entries");
  
  Ipv4AddressTrieMap::const_iterator longest_prefix_map = m_routes.longest_prefix_match (dest);
  if (longest_prefix_map == m_routes.end ())
    {
      return 0;
    }

  const Ipv4RoutingTableEntry & entry = (*longest_prefix_map->second)[entryNum];
  
  if (oif != 0 && oif == m_ipv4->GetNetDevice (entry.GetInterface ()))
    {
      NS_LOG_LOGIC ("Route points to the incoming interface. Return empty route");
      return 0;
    }
  
  // create a Ipv4Route object from the selected routing table entry
  Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
  rtentry->SetDestination (entry.GetDest ());
  rtentry->SetSource (m_ipv4->GetAddress (entry.GetInterface (), 0).GetLocal ());
  rtentry->SetGateway (entry.GetGateway ());
  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (entry.GetInterface ()));
  return rtentry;
}

void
Ipv4GlobalRoutingUnorderedNexthops::DeleteRoutes ()
{
  m_routes.clear ();
}

void
Ipv4GlobalRoutingUnorderedNexthops::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const
{
  std::ostream* os = stream->GetStream ();
  if (m_routes.size () > 0)
    {
      *os << "Destination    Iface(Metric),...,Iface(Metric)" << std::endl;
      for (Ipv4AddressTrieMap::const_iterator i=m_routes.begin (); i != m_routes.end (); i++)
        {
          if (i->second->size ()==0) continue;
          const Ipv4RoutingTableEntry &route = i->second->front ();

          std::ostringstream dest;
          dest << route.GetDest () << "/" << route.GetDestNetworkMask().GetPrefixLength ();
          *os << std::setiosflags (std::ios::left) << std::setw (15) << dest.str ();

          for (EntryContainer::iterator entry = i->second->begin ();
               entry != i->second->end ();
               entry ++)
            {
              if (entry != i->second->begin ())
                *os << ",";
              *os << entry->GetInterface () << "(" << entry->GetMetric () << ")";
            }

          *os << std::endl;
        }
    }
}

Ptr<Ipv4Route>
Ipv4GlobalRoutingUnorderedNexthops::RouteOutput (Ptr<Packet> p, const Ipv4Header &header,
                                          Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
{
//
// First, see if this is a multicast packet we have a route for.  If we
// have a route, then send the packet down each of the specified interfaces.
//
  if (header.GetDestination ().IsMulticast ())
    {
      NS_LOG_LOGIC ("Multicast destination-- returning false");
      return 0; // Let other routing protocols try to handle this
    }
//
// See if this is a unicast packet we have a route for.
//
  NS_LOG_LOGIC ("Unicast destination- looking up");
  Ptr<Ipv4Route> rtentry = LookupGlobal (0, header.GetDestination (), oif);
  if (rtentry)
    {
      sockerr = Socket::ERROR_NOTERROR;
    }
  else
    {
      sockerr = Socket::ERROR_NOROUTETOHOST;
    }
  return rtentry;
}

bool 
Ipv4GlobalRoutingUnorderedNexthops::RouteInput (Ptr<const Packet> p, const Ipv4Header &header,
                                         Ptr<const NetDevice> idev,
                                         UnicastForwardCallback ucb, MulticastForwardCallback mcb,
                                         LocalDeliverCallback lcb, ErrorCallback ecb)
{ 

  NS_LOG_FUNCTION (this << p << header << header.GetSource () << header.GetDestination () << idev);
  // Check if input device supports IP
  NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
  uint32_t iif = m_ipv4->GetInterfaceForDevice (idev);

  if (header.GetDestination ().IsMulticast ())
    {
      NS_LOG_LOGIC ("Multicast destination-- returning false");
      return false; // Let other routing protocols try to handle this
    }

  if (header.GetDestination ().IsBroadcast ())
    {
      NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
      // TODO:  Local Deliver for broadcast
      // TODO:  Forward broadcast
    }

  // TODO:  Configurable option to enable RFC 1222 Strong End System Model
  // Right now, we will be permissive and allow a source to send us
  // a packet to one of our other interface addresses; that is, the
  // destination unicast address does not match one of the iif addresses,
  // but we check our other interfaces.  This could be an option
  // (to remove the outer loop immediately below and just check iif).
  for (uint32_t j = 0; j < m_ipv4->GetNInterfaces (); j++)
    {
      for (uint32_t i = 0; i < m_ipv4->GetNAddresses (j); i++)
        {
          Ipv4InterfaceAddress iaddr = m_ipv4->GetAddress (j, i);
          Ipv4Address addr = iaddr.GetLocal ();
          if (addr.IsEqual (header.GetDestination ()))
            {
              if (j == iif)
                {
                  NS_LOG_LOGIC ("For me (destination " << addr << " match)");
                }
              else
                {
                  NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestination ());
                }
              lcb (p, header, iif);
              return true;
            }
          if (header.GetDestination ().IsEqual (iaddr.GetBroadcast ()))
            {
              NS_LOG_LOGIC ("For me (interface broadcast address)");
              lcb (p, header, iif);
              return true;
            }
          NS_LOG_LOGIC ("Address "<< addr << " not a match");
        }
    }
  // Check if input device supports IP forwarding
  if (m_ipv4->IsForwarding (iif) == false)
    {
      NS_LOG_LOGIC ("Forwarding disabled for this interface");
      ecb (p, header, Socket::ERROR_NOROUTETOHOST);
      return false;
    }
  // Next, try to find a route
  NS_LOG_LOGIC ("Unicast destination- looking up global route");
  Ptr<Ipv4Route> rtentry = LookupGlobal (0, header.GetDestination ());
  if (rtentry != 0)
    {
      NS_LOG_LOGIC ("Found unicast destination- calling unicast callback");
      ucb (rtentry, p, header);
      return true;
    }
  else
    {
      NS_LOG_LOGIC ("Did not find unicast destination- returning false");
      return false; // Let other routing protocols try to handle this
                    // route request.
    }
}

} // namespace ns3
