1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2016 Universita' degli Studi di Napoli Federico II
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 
19 #include "ns3/log.h"
20 #include "ipv4-queue-disc-item.h"
21 #include "ns3/tcp-header.h"
22 #include "ns3/udp-header.h"
23 
24 namespace ns3 {
25 
26 NS_LOG_COMPONENT_DEFINE ("Ipv4QueueDiscItem");
27 
Ipv4QueueDiscItem(Ptr<Packet> p,const Address & addr,uint16_t protocol,const Ipv4Header & header)28 Ipv4QueueDiscItem::Ipv4QueueDiscItem (Ptr<Packet> p, const Address& addr,
29                                       uint16_t protocol, const Ipv4Header & header)
30   : QueueDiscItem (p, addr, protocol),
31     m_header (header),
32     m_headerAdded (false)
33 {
34 }
35 
~Ipv4QueueDiscItem()36 Ipv4QueueDiscItem::~Ipv4QueueDiscItem ()
37 {
38   NS_LOG_FUNCTION (this);
39 }
40 
GetSize(void) const41 uint32_t Ipv4QueueDiscItem::GetSize (void) const
42 {
43   NS_LOG_FUNCTION (this);
44   Ptr<Packet> p = GetPacket ();
45   NS_ASSERT (p != 0);
46   uint32_t ret = p->GetSize ();
47   if (!m_headerAdded)
48     {
49       ret += m_header.GetSerializedSize ();
50     }
51   return ret;
52 }
53 
54 const Ipv4Header&
GetHeader(void) const55 Ipv4QueueDiscItem::GetHeader (void) const
56 {
57   return m_header;
58 }
59 
AddHeader(void)60 void Ipv4QueueDiscItem::AddHeader (void)
61 {
62   NS_LOG_FUNCTION (this);
63 
64   NS_ASSERT_MSG (!m_headerAdded, "The header has been already added to the packet");
65   Ptr<Packet> p = GetPacket ();
66   NS_ASSERT (p != 0);
67   p->AddHeader (m_header);
68   m_headerAdded = true;
69 }
70 
71 void
Print(std::ostream & os) const72 Ipv4QueueDiscItem::Print (std::ostream& os) const
73 {
74   if (!m_headerAdded)
75     {
76       os << m_header << " ";
77     }
78   os << GetPacket () << " "
79      << "Dst addr " << GetAddress () << " "
80      << "proto " << (uint16_t) GetProtocol () << " "
81      << "txq " << (uint16_t) GetTxQueueIndex ()
82   ;
83 }
84 
85 bool
Mark(void)86 Ipv4QueueDiscItem::Mark (void)
87 {
88   NS_LOG_FUNCTION (this);
89   if (!m_headerAdded && m_header.GetEcn () != Ipv4Header::ECN_NotECT)
90     {
91       m_header.SetEcn (Ipv4Header::ECN_CE);
92       return true;
93     }
94   return false;
95 }
96 
97 
98 bool
GetUint8Value(QueueItem::Uint8Values field,uint8_t & value) const99 Ipv4QueueDiscItem::GetUint8Value (QueueItem::Uint8Values field, uint8_t& value) const
100 {
101   bool ret = false;
102 
103   switch (field)
104     {
105     case IP_DSFIELD:
106       value = m_header.GetTos ();
107       ret = true;
108       break;
109     }
110 
111   return ret;
112 }
113 
114 uint32_t
Hash(uint32_t perturbation) const115 Ipv4QueueDiscItem::Hash (uint32_t perturbation) const
116 {
117   NS_LOG_FUNCTION (this << perturbation);
118 
119   Ipv4Address src = m_header.GetSource ();
120   Ipv4Address dest = m_header.GetDestination ();
121   uint8_t prot = m_header.GetProtocol ();
122   uint16_t fragOffset = m_header.GetFragmentOffset ();
123 
124   TcpHeader tcpHdr;
125   UdpHeader udpHdr;
126   uint16_t srcPort = 0;
127   uint16_t destPort = 0;
128 
129   if (prot == 6 && fragOffset == 0) // TCP
130     {
131       GetPacket ()->PeekHeader (tcpHdr);
132       srcPort = tcpHdr.GetSourcePort ();
133       destPort = tcpHdr.GetDestinationPort ();
134     }
135   else if (prot == 17 && fragOffset == 0) // UDP
136     {
137       GetPacket ()->PeekHeader (udpHdr);
138       srcPort = udpHdr.GetSourcePort ();
139       destPort = udpHdr.GetDestinationPort ();
140     }
141   if (prot != 6 && prot != 17)
142     {
143       NS_LOG_WARN ("Unknown transport protocol, no port number included in hash computation");
144     }
145 
146   /* serialize the 5-tuple and the perturbation in buf */
147   uint8_t buf[17];
148   src.Serialize (buf);
149   dest.Serialize (buf + 4);
150   buf[8] = prot;
151   buf[9] = (srcPort >> 8) & 0xff;
152   buf[10] = srcPort & 0xff;
153   buf[11] = (destPort >> 8) & 0xff;
154   buf[12] = destPort & 0xff;
155   buf[13] = (perturbation >> 24) & 0xff;
156   buf[14] = (perturbation >> 16) & 0xff;
157   buf[15] = (perturbation >> 8) & 0xff;
158   buf[16] = perturbation & 0xff;
159 
160   // Linux calculates jhash2 (jenkins hash), we calculate murmur3 because it is
161   // already available in ns-3
162   uint32_t hash = Hash32 ((char*) buf, 17);
163 
164   NS_LOG_DEBUG ("Hash value " << hash);
165 
166   return hash;
167 }
168 
169 } // namespace ns3
170