author | Tom Henderson <tomh@tomh.org> |
Thu, 28 May 2009 21:37:25 -0700 | |
changeset 4472 | e20a31541404 |
parent 4375 | db81fdcb06e7 |
child 4558 | 31e9053749bb |
permissions | -rw-r--r-- |
3820 | 1 |
#include "icmpv4-l4-protocol.h" |
4472
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
2 |
#include "ipv4-raw-socket-factory-impl.h" |
3820 | 3 |
#include "ipv4-interface.h" |
4 |
#include "ipv4-l3-protocol.h" |
|
5 |
#include "ns3/assert.h" |
|
6 |
#include "ns3/log.h" |
|
7 |
#include "ns3/node.h" |
|
8 |
#include "ns3/packet.h" |
|
9 |
#include "ns3/boolean.h" |
|
4472
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
10 |
#include "ns3/ipv4-route.h" |
3820 | 11 |
|
12 |
namespace ns3 { |
|
13 |
||
14 |
NS_LOG_COMPONENT_DEFINE ("Icmpv4L4Protocol"); |
|
15 |
||
16 |
NS_OBJECT_ENSURE_REGISTERED (Icmpv4L4Protocol); |
|
17 |
||
18 |
// see rfc 792 |
|
19 |
enum { |
|
20 |
ICMP_PROTOCOL = 1 |
|
21 |
}; |
|
22 |
||
23 |
TypeId |
|
24 |
Icmpv4L4Protocol::GetTypeId (void) |
|
25 |
{ |
|
26 |
static TypeId tid = TypeId ("ns3::Icmpv4L4Protocol") |
|
27 |
.SetParent<Ipv4L4Protocol> () |
|
28 |
.AddConstructor<Icmpv4L4Protocol> () |
|
29 |
.AddAttribute ("CalcChecksum", |
|
30 |
"Control whether the icmp header checksum is calculated and stored in outgoing icmpv4 headers", |
|
31 |
BooleanValue (false), |
|
32 |
MakeBooleanAccessor (&Icmpv4L4Protocol::m_calcChecksum), |
|
33 |
MakeBooleanChecker ()) |
|
34 |
; |
|
35 |
return tid; |
|
36 |
} |
|
37 |
||
38 |
Icmpv4L4Protocol::Icmpv4L4Protocol () |
|
39 |
: m_node (0) |
|
40 |
{} |
|
41 |
Icmpv4L4Protocol::~Icmpv4L4Protocol () |
|
42 |
{ |
|
43 |
NS_ASSERT (m_node == 0); |
|
44 |
} |
|
45 |
||
46 |
void |
|
47 |
Icmpv4L4Protocol::SetNode (Ptr<Node> node) |
|
48 |
{ |
|
49 |
m_node = node; |
|
50 |
} |
|
51 |
||
4472
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
52 |
/* |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
53 |
* This method is called by AddAgregate and completes the aggregation |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
54 |
* by setting the node in the ICMP stack and adding ICMP factory to |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
55 |
* IPv4 stack connected to the node |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
56 |
*/ |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
57 |
void |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
58 |
Icmpv4L4Protocol::NotifyNewAggregate () |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
59 |
{ |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
60 |
bool is_not_initialized = (m_node == 0); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
61 |
Ptr<Node>node = this->GetObject<Node> (); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
62 |
Ptr<Ipv4L3Protocol> ipv4 = this->GetObject<Ipv4L3Protocol> (); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
63 |
if (is_not_initialized && node!= 0 && ipv4 != 0) |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
64 |
{ |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
65 |
this->SetNode (node); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
66 |
ipv4->Insert (this); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
67 |
Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl> (); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
68 |
ipv4->AggregateObject (rawFactory); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
69 |
} |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
70 |
Object::NotifyNewAggregate (); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
71 |
} |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
72 |
|
3820 | 73 |
uint16_t |
74 |
Icmpv4L4Protocol::GetStaticProtocolNumber (void) |
|
75 |
{ |
|
76 |
return ICMP_PROTOCOL; |
|
77 |
} |
|
78 |
||
79 |
int |
|
80 |
Icmpv4L4Protocol::GetProtocolNumber (void) const |
|
81 |
{ |
|
82 |
return ICMP_PROTOCOL; |
|
83 |
} |
|
84 |
void |
|
85 |
Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code) |
|
86 |
{ |
|
87 |
Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> (); |
|
4472
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
88 |
NS_ASSERT (ipv4 != 0 && ipv4->GetRoutingProtocol () != 0); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
89 |
Ipv4Header header; |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
90 |
header.SetDestination (dest); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
91 |
Socket::SocketErrno errno; |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
92 |
Ptr<Ipv4Route> route; |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
93 |
uint32_t oif = 0; //specify non-zero if bound to a source address |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
94 |
route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
95 |
if (route != 0) |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
96 |
{ |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
97 |
NS_LOG_LOGIC ("Route exists"); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
98 |
Ipv4Address source = route->GetSource (); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
99 |
SendMessage (packet, source, dest, type, code, route); |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
100 |
} |
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
101 |
else |
3820 | 102 |
{ |
103 |
NS_LOG_WARN ("drop icmp message"); |
|
104 |
} |
|
105 |
} |
|
106 |
||
107 |
void |
|
4472
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
108 |
Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code, Ptr<Ipv4Route> route) |
3820 | 109 |
{ |
110 |
Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> (); |
|
111 |
Icmpv4Header icmp; |
|
112 |
icmp.SetType (type); |
|
113 |
icmp.SetCode (code); |
|
114 |
if (m_calcChecksum) |
|
115 |
{ |
|
116 |
icmp.EnableChecksum (); |
|
117 |
} |
|
118 |
packet->AddHeader (icmp); |
|
4472
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
119 |
ipv4->Send (packet, source, dest, ICMP_PROTOCOL, route); |
3820 | 120 |
} |
121 |
void |
|
122 |
Icmpv4L4Protocol::SendDestUnreachFragNeeded (Ipv4Header header, |
|
123 |
Ptr<const Packet> orgData, |
|
124 |
uint16_t nextHopMtu) |
|
125 |
{ |
|
126 |
NS_LOG_FUNCTION (this << header << *orgData << nextHopMtu); |
|
127 |
SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::FRAG_NEEDED, nextHopMtu); |
|
128 |
} |
|
129 |
void |
|
130 |
Icmpv4L4Protocol::SendDestUnreachPort (Ipv4Header header, |
|
131 |
Ptr<const Packet> orgData) |
|
132 |
{ |
|
133 |
NS_LOG_FUNCTION (this << header << *orgData); |
|
134 |
SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::PORT_UNREACHABLE, 0); |
|
135 |
} |
|
136 |
void |
|
137 |
Icmpv4L4Protocol::SendDestUnreach (Ipv4Header header, Ptr<const Packet> orgData, |
|
138 |
uint8_t code, uint16_t nextHopMtu) |
|
139 |
{ |
|
140 |
NS_LOG_FUNCTION (this << header << *orgData << (uint32_t) code << nextHopMtu); |
|
141 |
Ptr<Packet> p = Create<Packet> (); |
|
142 |
Icmpv4DestinationUnreachable unreach; |
|
143 |
unreach.SetNextHopMtu (nextHopMtu); |
|
144 |
unreach.SetHeader (header); |
|
145 |
unreach.SetData (orgData); |
|
146 |
p->AddHeader (unreach); |
|
147 |
SendMessage (p, header.GetSource (), Icmpv4Header::DEST_UNREACH, code); |
|
148 |
} |
|
149 |
||
150 |
void |
|
151 |
Icmpv4L4Protocol::SendTimeExceededTtl (Ipv4Header header, Ptr<const Packet> orgData) |
|
152 |
{ |
|
153 |
NS_LOG_FUNCTION (this << header << *orgData); |
|
154 |
Ptr<Packet> p = Create<Packet> (); |
|
155 |
Icmpv4TimeExceeded time; |
|
156 |
time.SetHeader (header); |
|
157 |
time.SetData (orgData); |
|
158 |
p->AddHeader (time); |
|
159 |
SendMessage (p, header.GetSource (), Icmpv4Header::TIME_EXCEEDED, Icmpv4TimeExceeded::TIME_TO_LIVE); |
|
160 |
} |
|
161 |
||
162 |
void |
|
163 |
Icmpv4L4Protocol::HandleEcho (Ptr<Packet> p, |
|
164 |
Icmpv4Header header, |
|
165 |
Ipv4Address source, |
|
166 |
Ipv4Address destination) |
|
167 |
{ |
|
168 |
NS_LOG_FUNCTION (this << p << header << source << destination); |
|
169 |
||
170 |
Ptr<Packet> reply = Create<Packet> (); |
|
171 |
Icmpv4Echo echo; |
|
172 |
p->RemoveHeader (echo); |
|
173 |
reply->AddHeader (echo); |
|
4472
e20a31541404
src/ and utils/ changes for IPv4 routing rework
Tom Henderson <tomh@tomh.org>
parents:
4375
diff
changeset
|
174 |
SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0, 0); |
3820 | 175 |
} |
176 |
void |
|
177 |
Icmpv4L4Protocol::Forward (Ipv4Address source, Icmpv4Header icmp, |
|
178 |
uint32_t info, Ipv4Header ipHeader, |
|
179 |
const uint8_t payload[8]) |
|
180 |
{ |
|
181 |
Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> (); |
|
182 |
Ptr<Ipv4L4Protocol> l4 = ipv4->GetProtocol (ipHeader.GetProtocol ()); |
|
183 |
if (l4 != 0) |
|
184 |
{ |
|
185 |
l4->ReceiveIcmp (source, ipHeader.GetTtl (), icmp.GetType (), icmp.GetCode (), |
|
186 |
info, ipHeader.GetSource (), ipHeader.GetDestination (), payload); |
|
187 |
} |
|
188 |
} |
|
189 |
void |
|
190 |
Icmpv4L4Protocol::HandleDestUnreach (Ptr<Packet> p, |
|
191 |
Icmpv4Header icmp, |
|
192 |
Ipv4Address source, |
|
193 |
Ipv4Address destination) |
|
194 |
{ |
|
195 |
NS_LOG_FUNCTION (this << p << icmp << source << destination); |
|
196 |
||
197 |
Icmpv4DestinationUnreachable unreach; |
|
198 |
p->PeekHeader (unreach); |
|
199 |
uint8_t payload[8]; |
|
200 |
unreach.GetData (payload); |
|
201 |
Ipv4Header ipHeader = unreach.GetHeader (); |
|
202 |
Forward (source, icmp, unreach.GetNextHopMtu (), ipHeader, payload); |
|
203 |
} |
|
204 |
void |
|
205 |
Icmpv4L4Protocol::HandleTimeExceeded (Ptr<Packet> p, |
|
206 |
Icmpv4Header icmp, |
|
207 |
Ipv4Address source, |
|
208 |
Ipv4Address destination) |
|
209 |
{ |
|
210 |
NS_LOG_FUNCTION (this << p << icmp << source << destination); |
|
211 |
||
212 |
Icmpv4TimeExceeded time; |
|
213 |
p->PeekHeader (time); |
|
214 |
uint8_t payload[8]; |
|
215 |
time.GetData (payload); |
|
216 |
Ipv4Header ipHeader = time.GetHeader (); |
|
217 |
// info field is zero for TimeExceeded on linux |
|
218 |
Forward (source, icmp, 0, ipHeader, payload); |
|
219 |
} |
|
220 |
||
221 |
enum Ipv4L4Protocol::RxStatus |
|
222 |
Icmpv4L4Protocol::Receive(Ptr<Packet> p, |
|
223 |
Ipv4Address const &source, |
|
224 |
Ipv4Address const &destination, |
|
225 |
Ptr<Ipv4Interface> incomingInterface) |
|
226 |
{ |
|
227 |
NS_LOG_FUNCTION (this << p << source << destination << incomingInterface); |
|
228 |
||
229 |
Icmpv4Header icmp; |
|
230 |
p->RemoveHeader (icmp); |
|
231 |
switch (icmp.GetType ()) { |
|
232 |
case Icmpv4Header::ECHO: |
|
233 |
HandleEcho (p, icmp, source, destination); |
|
234 |
break; |
|
235 |
case Icmpv4Header::DEST_UNREACH: |
|
236 |
HandleDestUnreach (p, icmp, source, destination); |
|
237 |
break; |
|
238 |
case Icmpv4Header::TIME_EXCEEDED: |
|
239 |
HandleTimeExceeded (p, icmp, source, destination); |
|
240 |
break; |
|
241 |
default: |
|
242 |
NS_LOG_DEBUG (icmp << " " << *p); |
|
243 |
break; |
|
244 |
} |
|
245 |
return Ipv4L4Protocol::RX_OK; |
|
246 |
} |
|
247 |
void |
|
248 |
Icmpv4L4Protocol::DoDispose (void) |
|
249 |
{ |
|
250 |
NS_LOG_FUNCTION (this); |
|
251 |
m_node = 0; |
|
252 |
Ipv4L4Protocol::DoDispose (); |
|
253 |
} |
|
254 |
||
255 |
} // namespace ns3 |