LEFT | RIGHT |
1 // -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- | 1 // -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- |
2 // | 2 // |
3 // Copyright (c) 2006 Georgia Tech Research Corporation | 3 // Copyright (c) 2006 Georgia Tech Research Corporation |
4 // | 4 // |
5 // This program is free software; you can redistribute it and/or modify | 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 | 6 // it under the terms of the GNU General Public License version 2 as |
7 // published by the Free Software Foundation; | 7 // published by the Free Software Foundation; |
8 // | 8 // |
9 // This program is distributed in the hope that it will be useful, | 9 // This program is distributed in the hope that it will be useful, |
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 TypeId· | 51 TypeId· |
52 Ipv4L3Protocol::GetTypeId (void) | 52 Ipv4L3Protocol::GetTypeId (void) |
53 { | 53 { |
54 static TypeId tid = TypeId ("ns3::Ipv4L3Protocol") | 54 static TypeId tid = TypeId ("ns3::Ipv4L3Protocol") |
55 .SetParent<Ipv4> () | 55 .SetParent<Ipv4> () |
56 .AddConstructor<Ipv4L3Protocol> () | 56 .AddConstructor<Ipv4L3Protocol> () |
57 .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing p
ackets generated on this node.", | 57 .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing p
ackets generated on this node.", |
58 UintegerValue (64), | 58 UintegerValue (64), |
59 MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl), | 59 MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl), |
60 MakeUintegerChecker<uint8_t> ()) | 60 MakeUintegerChecker<uint8_t> ()) |
| 61 .AddAttribute ("FragmentExpirationTimeout", |
| 62 "When this timeout expires, the fragments will be cleared fro
m the buffer.", |
| 63 TimeValue (Seconds (30)), |
| 64 MakeTimeAccessor (&Ipv4L3Protocol::m_fragmentExpirationTimeou
t), |
| 65 MakeTimeChecker ()) |
61 .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.", | 66 .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.", |
62 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace)) | 67 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace)) |
63 .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.", | 68 .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.", |
64 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace)) | 69 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace)) |
65 .AddTraceSource ("Drop", "Drop ipv4 packet", | 70 .AddTraceSource ("Drop", "Drop ipv4 packet", |
66 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace)) | 71 MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace)) |
67 .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to th
is Ipv4 stack.", | 72 .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to th
is Ipv4 stack.", |
68 ObjectVectorValue (), | 73 ObjectVectorValue (), |
69 MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces), | 74 MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces), |
70 MakeObjectVectorChecker<Ipv4Interface> ()) | 75 MakeObjectVectorChecker<Ipv4Interface> ()) |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 m_protocols.clear (); | 196 m_protocols.clear (); |
192 | 197 |
193 for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.
end (); ++i) | 198 for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.
end (); ++i) |
194 { | 199 { |
195 *i = 0; | 200 *i = 0; |
196 } | 201 } |
197 m_interfaces.clear (); | 202 m_interfaces.clear (); |
198 m_sockets.clear (); | 203 m_sockets.clear (); |
199 m_node = 0; | 204 m_node = 0; |
200 m_routingProtocol = 0; | 205 m_routingProtocol = 0; |
| 206 |
| 207 for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end
(); it++) |
| 208 { |
| 209 it->second = 0; |
| 210 } |
| 211 |
| 212 for (MapFragmentsTimers_t::iterator it = m_fragmentsTimers.begin (); it != m_f
ragmentsTimers.end (); it++) |
| 213 { |
| 214 if (it->second.IsRunning ()) |
| 215 { |
| 216 it->second.Cancel (); |
| 217 } |
| 218 } |
| 219 |
| 220 m_fragments.clear (); |
| 221 m_fragmentsTimers.clear (); |
| 222 |
201 Object::DoDispose (); | 223 Object::DoDispose (); |
202 } | 224 } |
203 | 225 |
204 void | 226 void |
205 Ipv4L3Protocol::SetupLoopback (void) | 227 Ipv4L3Protocol::SetupLoopback (void) |
206 { | 228 { |
207 NS_LOG_FUNCTION (this); | 229 NS_LOG_FUNCTION (this); |
208 | 230 |
209 Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> (); | 231 Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> (); |
210 Ptr<LoopbackNetDevice> device = 0; | 232 Ptr<LoopbackNetDevice> device = 0; |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (),
0); | 709 m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (),
0); |
688 return; | 710 return; |
689 } | 711 } |
690 packet->AddHeader (ipHeader); | 712 packet->AddHeader (ipHeader); |
691 Ptr<NetDevice> outDev = route->GetOutputDevice (); | 713 Ptr<NetDevice> outDev = route->GetOutputDevice (); |
692 int32_t interface = GetInterfaceForDevice (outDev); | 714 int32_t interface = GetInterfaceForDevice (outDev); |
693 NS_ASSERT (interface >= 0); | 715 NS_ASSERT (interface >= 0); |
694 Ptr<Ipv4Interface> outInterface = GetInterface (interface); | 716 Ptr<Ipv4Interface> outInterface = GetInterface (interface); |
695 NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4
InterfaceIndex " << interface); | 717 NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4
InterfaceIndex " << interface); |
696 | 718 |
697 NS_ASSERT_MSG (packet->GetSize () <= outInterface->GetDevice ()->GetMtu (),· | 719 if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0"))) |
698 "Packet size " << packet->GetSize () << " exceeds device MTU " | |
699 << outInterface->GetDevice ()->GetMtu () | |
700 << " for IPv4; fragmentation not supported"); | |
701 if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0"))) | |
702 { | 720 { |
703 if (outInterface->IsUp ()) | 721 if (outInterface->IsUp ()) |
704 { | 722 { |
705 NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ()); | 723 NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ()); |
706 m_txTrace (packet, m_node->GetObject<Ipv4> (), interface); | 724 if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () ) |
707 outInterface->Send (packet, route->GetGateway ()); | 725 { |
| 726 std::list<Ptr<Packet> > listFragments; |
| 727 DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), li
stFragments); |
| 728 for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (
); it != listFragments.end (); it++ ) |
| 729 { |
| 730 m_txTrace (*it, m_node->GetObject<Ipv4> (), interface); |
| 731 outInterface->Send (*it, route->GetGateway ()); |
| 732 } |
| 733 } |
| 734 else |
| 735 { |
| 736 m_txTrace (packet, m_node->GetObject<Ipv4> (), interface); |
| 737 outInterface->Send (packet, route->GetGateway ()); |
| 738 } |
708 } | 739 } |
709 else | 740 else |
710 { | 741 { |
711 NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->Get
Gateway ()); | 742 NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->Get
Gateway ()); |
712 Ipv4Header ipHeader; | 743 Ipv4Header ipHeader; |
713 packet->RemoveHeader (ipHeader); | 744 packet->RemoveHeader (ipHeader); |
714 m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<
Ipv4> (), interface); | 745 m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<
Ipv4> (), interface); |
715 } | 746 } |
716 }· | 747 }· |
717 else· | 748 else· |
718 { | 749 { |
719 if (outInterface->IsUp ()) | 750 if (outInterface->IsUp ()) |
720 { | 751 { |
721 NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); | 752 NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); |
722 m_txTrace (packet, m_node->GetObject<Ipv4> (), interface); | 753 if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () ) |
723 outInterface->Send (packet, ipHeader.GetDestination ()); | 754 { |
| 755 std::list<Ptr<Packet> > listFragments; |
| 756 DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), li
stFragments); |
| 757 for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (
); it != listFragments.end (); it++ ) |
| 758 { |
| 759 NS_LOG_LOGIC ("Sending fragment " << **it ); |
| 760 m_txTrace (*it, m_node->GetObject<Ipv4> (), interface); |
| 761 outInterface->Send (*it, ipHeader.GetDestination ()); |
| 762 } |
| 763 } |
| 764 else |
| 765 { |
| 766 m_txTrace (packet, m_node->GetObject<Ipv4> (), interface); |
| 767 outInterface->Send (packet, ipHeader.GetDestination ()); |
| 768 } |
724 } | 769 } |
725 else | 770 else |
726 { | 771 { |
727 NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.G
etDestination ()); | 772 NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.G
etDestination ()); |
728 Ipv4Header ipHeader; | 773 Ipv4Header ipHeader; |
729 packet->RemoveHeader (ipHeader); | 774 packet->RemoveHeader (ipHeader); |
730 m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<
Ipv4> (), interface); | 775 m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<
Ipv4> (), interface); |
731 } | 776 } |
732 } | 777 } |
733 } | 778 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 } | 839 } |
795 m_unicastForwardTrace (ipHeader, packet, interface); | 840 m_unicastForwardTrace (ipHeader, packet, interface); |
796 SendRealOut (rtentry, packet, ipHeader); | 841 SendRealOut (rtentry, packet, ipHeader); |
797 } | 842 } |
798 | 843 |
799 void | 844 void |
800 Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uin
t32_t iif) | 845 Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uin
t32_t iif) |
801 { | 846 { |
802 NS_LOG_FUNCTION (this << packet << &ip); | 847 NS_LOG_FUNCTION (this << packet << &ip); |
803 Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up | 848 Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up |
| 849 Ipv4Header ipHeader = ip; |
| 850 |
| 851 if ( !ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0 ) |
| 852 { |
| 853 NS_LOG_LOGIC ("Received a fragment, processing " << *p ); |
| 854 bool isPacketComplete; |
| 855 isPacketComplete = ProcessFragment (p, ipHeader, iif); |
| 856 if ( isPacketComplete == false) |
| 857 { |
| 858 return; |
| 859 } |
| 860 NS_LOG_LOGIC ("Got last fragment, Packet is complete " << *p ); |
| 861 } |
804 | 862 |
805 m_localDeliverTrace (ip, packet, iif); | 863 m_localDeliverTrace (ip, packet, iif); |
806 | 864 |
807 Ptr<IpL4Protocol> protocol = GetProtocol (ip.GetProtocol ()); | 865 Ptr<IpL4Protocol> protocol = GetProtocol (ip.GetProtocol ()); |
808 if (protocol != 0) | 866 if (protocol != 0) |
809 { | 867 { |
810 // we need to make a copy in the unlikely event we hit the | 868 // we need to make a copy in the unlikely event we hit the |
811 // RX_ENDPOINT_UNREACH codepath | 869 // RX_ENDPOINT_UNREACH codepath |
812 Ptr<Packet> copy = p->Copy (); | 870 Ptr<Packet> copy = p->Copy (); |
813 enum IpL4Protocol::RxStatus status =· | 871 enum IpL4Protocol::RxStatus status =· |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 } | 1107 } |
1050 | 1108 |
1051 void | 1109 void |
1052 Ipv4L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv4Header & ipHeade
r, Socket::SocketErrno sockErrno) | 1110 Ipv4L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv4Header & ipHeade
r, Socket::SocketErrno sockErrno) |
1053 { | 1111 { |
1054 NS_LOG_FUNCTION (this << p << ipHeader << sockErrno); | 1112 NS_LOG_FUNCTION (this << p << ipHeader << sockErrno); |
1055 NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " wit
h errno " << sockErrno);· | 1113 NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " wit
h errno " << sockErrno);· |
1056 m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0); | 1114 m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0); |
1057 } | 1115 } |
1058 | 1116 |
1059 } //namespace ns3 | 1117 void |
| 1118 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, uint32_t outIfaceMtu, std::
list<Ptr<Packet> >& listFragments) |
| 1119 { |
| 1120 // BEWARE: here we do assume that the header options are not present. |
| 1121 // a much more complex handling is necessary in case there are options. |
| 1122 // If (when) IPv4 option headers will be implemented, the following code shall
be changed. |
| 1123 // Of course also the reassemby code shall be changed as well. |
| 1124 |
| 1125 NS_LOG_FUNCTION (this << *packet << " - MTU: " << outIfaceMtu); |
| 1126 |
| 1127 Ptr<Packet> p = packet->Copy (); |
| 1128 |
| 1129 Ipv4Header ipv4Header; |
| 1130 p->RemoveHeader (ipv4Header); |
| 1131 |
| 1132 NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4), |
| 1133 "IPv4 fragmentation implementation only works without option he
aders." ); |
| 1134 |
| 1135 uint16_t offset = 0; |
| 1136 bool moreFragment = true; |
| 1137 uint16_t originalOffset = 0; |
| 1138 bool alreadyFragmented = false; |
| 1139 uint32_t currentFragmentablePartSize = 0; |
| 1140 |
| 1141 if (!ipv4Header.IsLastFragment()) |
| 1142 { |
| 1143 alreadyFragmented = true; |
| 1144 originalOffset = ipv4Header.GetFragmentOffset(); |
| 1145 } |
| 1146 |
| 1147 // IPv4 fragments are all 8 bytes aligned but the last. |
| 1148 // The IP payload size is: |
| 1149 // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8 |
| 1150 uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~ui
nt32_t (0x7); |
| 1151 |
| 1152 NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize ); |
| 1153 |
| 1154 do |
| 1155 { |
| 1156 Ipv4Header fragmentHeader = ipv4Header; |
| 1157 |
| 1158 if (p->GetSize () > offset + fragmentSize ) |
| 1159 { |
| 1160 moreFragment = true; |
| 1161 currentFragmentablePartSize = fragmentSize; |
| 1162 fragmentHeader.SetMoreFragments (); |
| 1163 } |
| 1164 else |
| 1165 { |
| 1166 moreFragment = false; |
| 1167 currentFragmentablePartSize = p->GetSize () - offset; |
| 1168 if (alreadyFragmented) |
| 1169 { |
| 1170 fragmentHeader.SetMoreFragments (); |
| 1171 } |
| 1172 else |
| 1173 { |
| 1174 fragmentHeader.SetLastFragment (); |
| 1175 } |
| 1176 } |
| 1177 |
| 1178 NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmenta
blePartSize ); |
| 1179 Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartS
ize); |
| 1180 NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize
() ); |
| 1181 |
| 1182 fragmentHeader.SetFragmentOffset (offset+originalOffset); |
| 1183 fragmentHeader.SetPayloadSize (currentFragmentablePartSize); |
| 1184 |
| 1185 if (Node::ChecksumEnabled ()) |
| 1186 { |
| 1187 fragmentHeader.EnableChecksum (); |
| 1188 } |
| 1189 |
| 1190 NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset ()
); |
| 1191 |
| 1192 NS_LOG_LOGIC ("New fragment Header " << fragmentHeader); |
| 1193 fragment->AddHeader (fragmentHeader); |
| 1194 |
| 1195 std::ostringstream oss; |
| 1196 fragment->Print (oss); |
| 1197 |
| 1198 NS_LOG_LOGIC ("New fragment " << *fragment); |
| 1199 |
| 1200 listFragments.push_back (fragment); |
| 1201 |
| 1202 offset += currentFragmentablePartSize; |
| 1203 |
| 1204 } |
| 1205 while (moreFragment); |
| 1206 |
| 1207 return; |
| 1208 } |
| 1209 |
| 1210 bool |
| 1211 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint
32_t iif) |
| 1212 { |
| 1213 NS_LOG_FUNCTION (this << packet << " " << ipHeader << " " << iif); |
| 1214 |
| 1215 uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 &
uint64_t (ipHeader.GetDestination ().Get ()); |
| 1216 uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 & uint32_t (
ipHeader.GetProtocol ()); |
| 1217 std::pair<uint64_t, uint32_t> key; |
| 1218 bool ret = false; |
| 1219 Ptr<Packet> p = packet->Copy (); |
| 1220 |
| 1221 key.first = addressCombination; |
| 1222 key.second = idProto; |
| 1223 |
| 1224 Ptr<Fragments> fragments; |
| 1225 |
| 1226 MapFragments_t::iterator it = m_fragments.find (key); |
| 1227 if (it == m_fragments.end ()) |
| 1228 { |
| 1229 fragments = Create<Fragments> (); |
| 1230 m_fragments.insert (std::make_pair (key, fragments)); |
| 1231 m_fragmentsTimers[key] = Simulator::Schedule (m_fragmentExpirationTimeout, |
| 1232 &Ipv4L3Protocol::HandleFragm
entsTimeout, this, |
| 1233 key, ipHeader, iif); |
| 1234 } |
| 1235 else |
| 1236 { |
| 1237 fragments = it->second; |
| 1238 } |
| 1239 |
| 1240 NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset:
" << (ipHeader.GetFragmentOffset ()) ); |
| 1241 |
| 1242 fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFrag
ment () ); |
| 1243 |
| 1244 if ( fragments->IsEntire () ) |
| 1245 { |
| 1246 packet = fragments->GetPacket (); |
| 1247 fragments = 0; |
| 1248 m_fragments.erase (key); |
| 1249 if (m_fragmentsTimers[key].IsRunning ()) |
| 1250 { |
| 1251 NS_LOG_LOGIC ("Stopping WaitFragmentsTimer at " << Simulator::Now ().G
etSeconds () << " due to complete packet"); |
| 1252 m_fragmentsTimers[key].Cancel (); |
| 1253 } |
| 1254 m_fragmentsTimers.erase (key); |
| 1255 ret = true; |
| 1256 } |
| 1257 |
| 1258 return ret; |
| 1259 } |
| 1260 |
| 1261 Ipv4L3Protocol::Fragments::Fragments () |
| 1262 : m_moreFragment (0) |
| 1263 { |
| 1264 } |
| 1265 |
| 1266 Ipv4L3Protocol::Fragments::~Fragments () |
| 1267 { |
| 1268 } |
| 1269 |
| 1270 void |
| 1271 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentO
ffset, bool moreFragment) |
| 1272 { |
| 1273 NS_LOG_FUNCTION (this << fragment << " " << fragmentOffset << " " << moreFragm
ent); |
| 1274 |
| 1275 std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it; |
| 1276 |
| 1277 for (it = m_fragments.begin (); it != m_fragments.end (); it++) |
| 1278 { |
| 1279 if (it->second > fragmentOffset) |
| 1280 { |
| 1281 break; |
| 1282 } |
| 1283 } |
| 1284 |
| 1285 if (it == m_fragments.end ()) |
| 1286 { |
| 1287 m_moreFragment = moreFragment; |
| 1288 } |
| 1289 |
| 1290 m_fragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragm
entOffset)); |
| 1291 } |
| 1292 |
| 1293 bool |
| 1294 Ipv4L3Protocol::Fragments::IsEntire () const |
| 1295 { |
| 1296 NS_LOG_FUNCTION (this); |
| 1297 |
| 1298 bool ret = !m_moreFragment && m_fragments.size () > 0; |
| 1299 |
| 1300 if (ret) |
| 1301 { |
| 1302 uint16_t lastEndOffset = 0; |
| 1303 |
| 1304 for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_f
ragments.begin (); it != m_fragments.end (); it++) |
| 1305 { |
| 1306 // overlapping fragments do exist |
| 1307 NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->se
cond ); |
| 1308 |
| 1309 if (lastEndOffset < it->second) |
| 1310 { |
| 1311 ret = false; |
| 1312 break; |
| 1313 } |
| 1314 // fragments might overlap in strange ways |
| 1315 uint16_t fragmentEnd = it->first->GetSize () + it->second; |
| 1316 lastEndOffset = std::max ( lastEndOffset, fragmentEnd ); |
| 1317 } |
| 1318 } |
| 1319 |
| 1320 return ret; |
| 1321 } |
| 1322 |
| 1323 Ptr<Packet> |
| 1324 Ipv4L3Protocol::Fragments::GetPacket () const |
| 1325 { |
| 1326 NS_LOG_FUNCTION (this); |
| 1327 |
| 1328 std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.
begin (); |
| 1329 |
| 1330 Ptr<Packet> p = Create<Packet> (); |
| 1331 uint16_t lastEndOffset = 0; |
| 1332 |
| 1333 for ( it = m_fragments.begin (); it != m_fragments.end (); it++) |
| 1334 { |
| 1335 if ( lastEndOffset > it->second ) |
| 1336 { |
| 1337 // The fragments are overlapping. |
| 1338 // We do not overwrite the "old" with the "new" because we do not know
when each arrived. |
| 1339 // This is different from what Linux does. |
| 1340 // It is not possible to emulate a fragmentation attack. |
| 1341 uint32_t newStart = lastEndOffset - it->second; |
| 1342 if ( it->first->GetSize () > newStart ) |
| 1343 { |
| 1344 uint32_t newSize = it->first->GetSize () - newStart; |
| 1345 Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, ne
wSize); |
| 1346 p->AddAtEnd (tempFragment); |
| 1347 } |
| 1348 } |
| 1349 else |
| 1350 { |
| 1351 NS_LOG_LOGIC ("Adding: " << *(it->first) ); |
| 1352 p->AddAtEnd (it->first); |
| 1353 } |
| 1354 lastEndOffset = p->GetSize (); |
| 1355 } |
| 1356 |
| 1357 return p; |
| 1358 } |
| 1359 |
| 1360 Ptr<Packet> |
| 1361 Ipv4L3Protocol::Fragments::GetPartialPacket () const |
| 1362 { |
| 1363 std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.
begin (); |
| 1364 |
| 1365 Ptr<Packet> p = Create<Packet> (); |
| 1366 uint16_t lastEndOffset = 0; |
| 1367 |
| 1368 if ( m_fragments.begin ()->second > 0 ) |
| 1369 { |
| 1370 return p; |
| 1371 } |
| 1372 |
| 1373 for ( it = m_fragments.begin (); it != m_fragments.end (); it++) |
| 1374 { |
| 1375 if ( lastEndOffset > it->second ) |
| 1376 { |
| 1377 uint32_t newStart = lastEndOffset - it->second; |
| 1378 uint32_t newSize = it->first->GetSize () - newStart; |
| 1379 Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSiz
e); |
| 1380 p->AddAtEnd (tempFragment); |
| 1381 } |
| 1382 else if ( lastEndOffset == it->second ) |
| 1383 { |
| 1384 NS_LOG_LOGIC ("Adding: " << *(it->first) ); |
| 1385 p->AddAtEnd (it->first); |
| 1386 } |
| 1387 lastEndOffset = p->GetSize (); |
| 1388 } |
| 1389 |
| 1390 return p; |
| 1391 } |
| 1392 |
| 1393 void |
| 1394 Ipv4L3Protocol::HandleFragmentsTimeout (std::pair<uint64_t, uint32_t> key, Ipv4H
eader & ipHeader, uint32_t iif) |
| 1395 { |
| 1396 NS_LOG_FUNCTION (this); |
| 1397 |
| 1398 MapFragments_t::iterator it = m_fragments.find (key); |
| 1399 Ptr<Packet> packet = it->second->GetPartialPacket (); |
| 1400 |
| 1401 // if we have at least 8 bytes, we can send an ICMP. |
| 1402 if ( packet->GetSize () > 8 ) |
| 1403 { |
| 1404 Ptr<Icmpv4L4Protocol> icmp = GetIcmp (); |
| 1405 icmp->SendTimeExceededTtl (ipHeader, packet); |
| 1406 } |
| 1407 m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, m_node->GetObject<Ipv4>
(), iif); |
| 1408 |
| 1409 // clear the buffers |
| 1410 it->second = 0; |
| 1411 |
| 1412 m_fragments.erase (key); |
| 1413 m_fragmentsTimers.erase (key); |
| 1414 } |
| 1415 |
| 1416 } // namespace ns3 |
LEFT | RIGHT |