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) 2010 Lalith Suresh | 3 * Copyright (c) 2010 Lalith Suresh |
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 |
(...skipping 11 matching lines...) Expand all Loading... |
22 #ifdef NS3_CLICK | 22 #ifdef NS3_CLICK |
23 | 23 |
24 #include "ns3/node.h" | 24 #include "ns3/node.h" |
25 #include "ns3/simulator.h" | 25 #include "ns3/simulator.h" |
26 #include "ns3/log.h" | 26 #include "ns3/log.h" |
27 #include "ns3/mac48-address.h" | 27 #include "ns3/mac48-address.h" |
28 #include "ns3/ipv4-interface.h" | 28 #include "ns3/ipv4-interface.h" |
29 #include "ns3/ipv4-l3-click-protocol.h" | 29 #include "ns3/ipv4-l3-click-protocol.h" |
30 | 30 |
31 #include "ipv4-click-routing.h" | 31 #include "ipv4-click-routing.h" |
32 #include "ipv4-external-routing.h" | |
33 #include <string> | 32 #include <string> |
34 #include <map> | 33 #include <map> |
35 | 34 |
36 #include <cstdlib> | 35 #include <cstdlib> |
37 #include <cstdarg> | 36 #include <cstdarg> |
38 | 37 |
39 NS_LOG_COMPONENT_DEFINE ("Ipv4ClickRouting"); | 38 NS_LOG_COMPONENT_DEFINE ("Ipv4ClickRouting"); |
40 | 39 |
41 namespace ns3 { | 40 namespace ns3 { |
42 | 41 |
| 42 // Values from nsclick ExtRouter implementation |
| 43 #define INTERFACE_ID_KERNELTAP 0 |
| 44 #define INTERFACE_ID_FIRST 1 |
| 45 #define INTERFACE_ID_FIRST_DROP 33· |
| 46 |
43 NS_OBJECT_ENSURE_REGISTERED (Ipv4ClickRouting); | 47 NS_OBJECT_ENSURE_REGISTERED (Ipv4ClickRouting); |
44 | 48 |
45 std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickI
nstanceFromSimNode; | 49 std::map < simclick_node_t *, Ptr<Ipv4ClickRouting> > Ipv4ClickRouting::m_clickI
nstanceFromSimNode; |
46 | 50 |
47 TypeId | 51 TypeId |
48 Ipv4ClickRouting::GetTypeId (void) | 52 Ipv4ClickRouting::GetTypeId (void) |
49 { | 53 { |
50 static TypeId tid = TypeId ("ns3::Ipv4ClickRouting") | 54 static TypeId tid = TypeId ("ns3::Ipv4ClickRouting") |
51 .SetParent<Ipv4ExternalRouting> () | 55 .SetParent<Ipv4RoutingProtocol> () |
52 .AddConstructor<Ipv4ClickRouting> () | 56 .AddConstructor<Ipv4ClickRouting> () |
53 ; | 57 ; |
54 | 58 |
55 return tid; | 59 return tid; |
56 } | 60 } |
57 | 61 |
58 Ipv4ClickRouting::Ipv4ClickRouting () | 62 Ipv4ClickRouting::Ipv4ClickRouting () |
59 : m_nonDefaultName (false), | 63 : m_nonDefaultName (false), |
60 m_ipv4 (0) | 64 m_ipv4 (0) |
61 { | 65 { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 Ipv4ClickRouting::GetNodeName () | 142 Ipv4ClickRouting::GetNodeName () |
139 { | 143 { |
140 return m_nodeName; | 144 return m_nodeName; |
141 } | 145 } |
142 | 146 |
143 int | 147 int |
144 Ipv4ClickRouting::GetInterfaceId (const char *ifname) | 148 Ipv4ClickRouting::GetInterfaceId (const char *ifname) |
145 { | 149 { |
146 int retval = -1; | 150 int retval = -1; |
147 | 151 |
148 // Tap/tun devices refer to the kernel | 152 // The below hard coding of interface names follows the |
| 153 // same approach as used in the original nsclick code for |
| 154 // ns-2. The interface names map directly to what is to |
| 155 // be used in the Click configuration files. |
| 156 // Thus eth0 will refer to the first network device of |
| 157 // the node, and is to be named so in the Click graph. |
| 158 // This function is called by Click during the intialisation |
| 159 // phase of the Click graph, during which it tries to map |
| 160 // interface IDs to interface names. The return value |
| 161 // corresponds to the interface ID that Click will use. |
| 162 |
| 163 // Tap/tun devices refer to the kernel devices |
149 if (strstr(ifname, "tap") || strstr(ifname, "tun")) | 164 if (strstr(ifname, "tap") || strstr(ifname, "tun")) |
150 { | 165 { |
151 retval = ExtRouter::IFID_KERNELTAP; | 166 retval = 0; |
152 } | 167 } |
153 else if (const char *devname = strstr(ifname, "eth")) | 168 else if (const char *devname = strstr(ifname, "eth")) |
154 { | 169 { |
155 while (*devname && !isdigit((unsigned char) *devname)) | 170 while (*devname && !isdigit((unsigned char) *devname)) |
156 { | 171 { |
157 devname++; | 172 devname++; |
158 } | 173 } |
159 | 174 |
160 if (*devname) | 175 if (*devname) |
161 { | 176 { |
162 retval = atoi(devname) + ExtRouter::IFID_FIRSTIF; | 177 retval = atoi(devname) + INTERFACE_ID_FIRST; |
163 } | 178 } |
164 } | 179 } |
165 else if (const char *devname = strstr(ifname, "drop")) | 180 else if (const char *devname = strstr(ifname, "drop")) |
166 { | 181 { |
167 while (*devname && !isdigit((unsigned char) *devname)) | 182 while (*devname && !isdigit((unsigned char) *devname)) |
168 { | 183 { |
169 devname++; | 184 devname++; |
170 } | 185 } |
171 if (*devname) | 186 if (*devname) |
172 { | 187 { |
173 retval = atoi(devname) + ExtRouter::IFID_FIRSTIFDROP; | 188 retval = atoi(devname) + INTERFACE_ID_FIRST_DROP; |
174 } | 189 } |
175 } | 190 } |
176 | 191 |
177 return retval; | 192 return retval; |
178 } | 193 } |
179 | 194 |
180 int | 195 bool |
181 Ipv4ClickRouting::IfReady (int ifid) | 196 Ipv4ClickRouting::IsInterfaceReady (int ifid) |
182 { | 197 { |
183 if (ifid >= 0 && ifid < (int) m_ipv4->GetNInterfaces ()) | 198 if (ifid >= 0 && ifid < (int) m_ipv4->GetNInterfaces ()) |
184 { | 199 { |
185 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4
); | 200 return true; |
186 // Check for any underlying queue | |
187 Ptr<NetDevice> netdev = ipv4l3->GetNetDevice (ifid); | |
188 if (netdev->IsTxBusy()) | |
189 return 0; | |
190 else | |
191 return 1; | |
192 } | 201 } |
193 else | 202 else |
194 { | 203 { |
195 return 0; | 204 return false; |
196 } | 205 } |
197 } | 206 } |
198 | 207 |
199 std::string | 208 std::string |
200 Ipv4ClickRouting::GetIpAddrFromIfid (int ifid) | 209 Ipv4ClickRouting::GetIpAddressFromInterfaceId (int ifid) |
201 { | 210 { |
202 std::stringstream addr; | 211 std::stringstream addr; |
203 m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr); | 212 m_ipv4->GetAddress (ifid, 0).GetLocal ().Print (addr); |
204 | 213 |
205 return addr.str (); | 214 return addr.str (); |
206 } | 215 } |
207 | 216 |
208 std::string | 217 std::string |
209 Ipv4ClickRouting::GetMacAddrFromIfid (int ifid) | 218 Ipv4ClickRouting::GetMacAddressFromInterfaceId (int ifid) |
210 { | 219 { |
211 std::stringstream addr; | 220 std::stringstream addr; |
212 | 221 |
213 Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid); | 222 Ptr<NetDevice> device = m_ipv4->GetNetDevice (ifid); |
214 Address devAddr = device->GetAddress (); | 223 Address devAddr = device->GetAddress (); |
215 addr << Mac48Address::ConvertFrom(devAddr); | 224 addr << Mac48Address::ConvertFrom(devAddr); |
216 | 225 |
217 return addr.str (); | 226 return addr.str (); |
218 } | 227 } |
219 | 228 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 // Note: There are probably use-cases for returning | 372 // Note: There are probably use-cases for returning |
364 // a write handler's error code, so don't assert. | 373 // a write handler's error code, so don't assert. |
365 // For example, the 'add' handler for IPRouteTable | 374 // For example, the 'add' handler for IPRouteTable |
366 // type elements fails if the route to be added | 375 // type elements fails if the route to be added |
367 // already exists. | 376 // already exists. |
368 | 377 |
369 return r; | 378 return r; |
370 } | 379 } |
371 | 380 |
372 void | 381 void |
373 Ipv4ClickRouting::SetPromisc (std::string ifName) | 382 Ipv4ClickRouting::SetPromiscuous (std::string ifName) |
374 { | 383 { |
375 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4); | 384 Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4); |
376 NS_ASSERT(ipv4l3); | 385 NS_ASSERT(ipv4l3); |
377 // Interface ethN gets index 1+N, but netdevice will start at 0 | 386 // Interface ethN gets index 1+N, but netdevice will start at 0 |
378 // To ensure this, install a Click stack on a node only after | 387 // To ensure this, install a Click stack on a node only after |
379 // all NetDevices have been installed. | 388 // all NetDevices have been installed. |
380 ipv4l3->SetPromisc (GetInterfaceId (ifName.c_str ()) - 1); | 389 ipv4l3->SetPromisc (GetInterfaceId (ifName.c_str ()) - 1); |
381 } | 390 } |
382 | 391 |
383 Ptr<Ipv4Route> | 392 Ptr<Ipv4Route> |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 { | 438 { |
430 NS_LOG_DEBUG ("Click node " << m_nodeName | 439 NS_LOG_DEBUG ("Click node " << m_nodeName |
431 << ": RouteOutput for dest=" << header.GetDest
ination () | 440 << ": RouteOutput for dest=" << header.GetDest
ination () |
432 << " No route to host"); | 441 << " No route to host"); |
433 sockerr = Socket::ERROR_NOROUTETOHOST; | 442 sockerr = Socket::ERROR_NOROUTETOHOST; |
434 } | 443 } |
435 | 444 |
436 return rtentry; | 445 return rtentry; |
437 } | 446 } |
438 | 447 |
| 448 // This method should never be called since Click handles |
| 449 // forwarding directly |
| 450 bool |
| 451 Ipv4ClickRouting::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, |
| 452 Ptr<const NetDevice> idev, UnicastForwardCallback
ucb, |
| 453 MulticastForwardCallback mcb, LocalDeliverCallbac
k lcb,· |
| 454 ErrorCallback ecb) |
| 455 { |
| 456 NS_FATAL_ERROR ("Click router does not have a RouteInput() interface!"); |
| 457 return false; |
| 458 } |
| 459 |
439 void | 460 void |
440 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const | 461 Ipv4ClickRouting::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const |
441 { | 462 { |
442 } | 463 } |
443 | 464 |
| 465 void |
| 466 Ipv4ClickRouting::NotifyInterfaceUp (uint32_t i) |
| 467 {} |
| 468 |
| 469 void |
| 470 Ipv4ClickRouting::NotifyInterfaceDown (uint32_t i) |
| 471 {} |
| 472 |
| 473 void |
| 474 Ipv4ClickRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress add
ress) |
| 475 {} |
| 476 |
| 477 void |
| 478 Ipv4ClickRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress
address) |
| 479 {} |
| 480 |
| 481 |
444 } // namespace ns3 | 482 } // namespace ns3 |
445 | 483 |
446 #ifdef __cplusplus | 484 static int simstrlcpy(char *buf, int len, const std::string &s) |
447 extern "C" | 485 { |
448 { | |
449 #endif | |
450 | |
451 using namespace ns3; | |
452 | |
453 static int simstrlcpy(char *buf, int len, const std::string &s) { | |
454 if (len) | 486 if (len) |
455 { | 487 { |
456 len--; | 488 len--; |
457 | 489 |
458 if ((unsigned) len > s.length()) | 490 if ((unsigned) len > s.length()) |
459 { | 491 { |
460 len = s.length(); | 492 len = s.length(); |
461 } | 493 } |
462 | 494 |
463 s.copy(buf, len); | 495 s.copy(buf, len); |
464 buf[len] = '\0'; | 496 buf[len] = '\0'; |
465 } | 497 } |
466 return 0; | 498 return 0; |
467 } | 499 } |
468 | 500 |
469 // Sends a Packet from Click to the Simulator: Defined in simclick.h | 501 // Sends a Packet from Click to the Simulator: Defined in simclick.h. Click |
| 502 // calls these methods. |
470 int simclick_sim_send(simclick_node_t *simnode, | 503 int simclick_sim_send(simclick_node_t *simnode, |
471 int ifid, int type, const unsigned char* data, int len, | 504 int ifid, int type, const unsigned char* data, int len, |
472 simclick_simpacketinfo *pinfo) | 505 simclick_simpacketinfo *pinfo) |
473 { | 506 { |
474 NS_LOG_DEBUG ("simclick_sim_send called at " <<Simulator::Now().GetSeconds()<<
": " << ifid << " " << type << " " << data << " "<< len); | 507 NS_LOG_DEBUG ("simclick_sim_send called at " << ns3::Simulator::Now().GetSecon
ds()<<": " << ifid << " " << type << " " << data << " "<< len); |
475 | 508 |
476 if (simnode == NULL) | 509 if (simnode == NULL) |
477 { | 510 { |
478 return -1; | 511 return -1; |
479 } | 512 } |
480 | 513 |
481 Ptr<Ipv4ClickRouting> clickInstance = Ipv4ClickRouting::GetClickInstanceFromSi
mNode (simnode); | 514 ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClic
kInstanceFromSimNode (simnode); |
482 | 515 |
483 clickInstance->HandlePacketFromClick (ifid, type, data, len); | 516 clickInstance->HandlePacketFromClick (ifid, type, data, len); |
484 | 517 |
485 return 0; | 518 return 0; |
486 } | 519 } |
487 | 520 |
488 // Click Service Methods: Defined in simclick.h | 521 // Click Service Methods: Defined in simclick.h |
489 int simclick_sim_command(simclick_node_t *simnode, int cmd, ...) | 522 int simclick_sim_command(simclick_node_t *simnode, int cmd, ...) |
490 { | 523 { |
491 va_list val; | 524 va_list val; |
492 va_start (val, cmd); | 525 va_start (val, cmd); |
493 | 526 |
494 int retval = 0; | 527 int retval = 0; |
495 | 528 |
496 Ptr<Ipv4ClickRouting> clickInstance = Ipv4ClickRouting::GetClickInstanceFromSi
mNode (simnode); | 529 ns3::Ptr<ns3::Ipv4ClickRouting> clickInstance = ns3::Ipv4ClickRouting::GetClic
kInstanceFromSimNode (simnode); |
497 switch (cmd)· | 530 switch (cmd)· |
498 { | 531 { |
499 case SIMCLICK_VERSION: | 532 case SIMCLICK_VERSION: |
500 { | 533 { |
501 retval = 0; | 534 retval = 0; |
502 break; | 535 break; |
503 } | 536 } |
504 | 537 |
505 case SIMCLICK_SUPPORTS: | 538 case SIMCLICK_SUPPORTS: |
506 { | 539 { |
(...skipping 15 matching lines...) Expand all Loading... |
522 case SIMCLICK_IPADDR_FROM_NAME: | 555 case SIMCLICK_IPADDR_FROM_NAME: |
523 { | 556 { |
524 const char *ifname = va_arg(val, const char *); | 557 const char *ifname = va_arg(val, const char *); |
525 char *buf = va_arg(val, char *); | 558 char *buf = va_arg(val, char *); |
526 int len = va_arg(val, int); | 559 int len = va_arg(val, int); |
527 | 560 |
528 int ifid = clickInstance->GetInterfaceId (ifname); | 561 int ifid = clickInstance->GetInterfaceId (ifname); |
529 | 562 |
530 if (ifid >= 0) | 563 if (ifid >= 0) |
531 { | 564 { |
532 retval = simstrlcpy(buf, len, clickInstance->GetIpAddrFromIfid (ifid
)); | 565 retval = simstrlcpy(buf, len, clickInstance->GetIpAddressFromInterfa
ceId (ifid)); |
533 } | 566 } |
534 else | 567 else |
535 { | 568 { |
536 retval = -1; | 569 retval = -1; |
537 } | 570 } |
538 | 571 |
539 NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPADDR_FROM_NA
ME: "<< ifname << " "<< buf << " " << len); | 572 NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IPADDR_FROM_NA
ME: "<< ifname << " "<< buf << " " << len); |
540 break; | 573 break; |
541 } | 574 } |
542 | 575 |
543 case SIMCLICK_MACADDR_FROM_NAME: | 576 case SIMCLICK_MACADDR_FROM_NAME: |
544 { | 577 { |
545 const char *ifname = va_arg(val, const char *); | 578 const char *ifname = va_arg(val, const char *); |
546 char *buf = va_arg(val, char *); | 579 char *buf = va_arg(val, char *); |
547 int len = va_arg(val, int); | 580 int len = va_arg(val, int); |
548 int ifid = clickInstance->GetInterfaceId (ifname); | 581 int ifid = clickInstance->GetInterfaceId (ifname); |
549 | 582 |
550 if (ifid >= 0) | 583 if (ifid >= 0) |
551 { | 584 { |
552 retval = simstrlcpy(buf, len, clickInstance->GetMacAddrFromIfid (ifi
d)); | 585 retval = simstrlcpy(buf, len, clickInstance->GetMacAddressFromInterf
aceId (ifid)); |
553 } | 586 } |
554 else | 587 else |
555 { | 588 { |
556 retval = -1; | 589 retval = -1; |
557 } | 590 } |
558 | 591 |
559 NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_MACADDR_FROM_N
AME: "<< ifname << " "<< buf << " "<< len); | 592 NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_MACADDR_FROM_N
AME: "<< ifname << " "<< buf << " "<< len); |
560 break; | 593 break; |
561 } | 594 } |
562 | 595 |
(...skipping 17 matching lines...) Expand all Loading... |
580 | 613 |
581 NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_GET_NODE_NAME:
" << buf << " " << len); | 614 NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_GET_NODE_NAME:
" << buf << " " << len); |
582 break; | 615 break; |
583 } | 616 } |
584 | 617 |
585 case SIMCLICK_IF_READY: | 618 case SIMCLICK_IF_READY: |
586 { | 619 { |
587 int ifid = va_arg(val, int); // Commented out so that optimized build wo
rks | 620 int ifid = va_arg(val, int); // Commented out so that optimized build wo
rks |
588 | 621 |
589 // We're not using a ClickQueue, so we're always ready (for the timebein
g) | 622 // We're not using a ClickQueue, so we're always ready (for the timebein
g) |
590 retval = clickInstance->IfReady (ifid); | 623 retval = clickInstance->IsInterfaceReady (ifid); |
591 | 624 |
592 NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_READY: " <<
ifid << " " << Simulator::Now ()); | 625 NS_LOG_DEBUG (clickInstance->GetNodeName () << " SIMCLICK_IF_READY: " <<
ifid << " " << ns3::Simulator::Now ()); |
593 break; | 626 break; |
594 } | 627 } |
595 | 628 |
596 case SIMCLICK_TRACE: | 629 case SIMCLICK_TRACE: |
597 { | 630 { |
598 // Used only for tracing | 631 // Used only for tracing |
599 NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIM
CLICK_TRACE"); | 632 NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIM
CLICK_TRACE"); |
600 break; | 633 break; |
601 } | 634 } |
602 | 635 |
603 case SIMCLICK_GET_NODE_ID: | 636 case SIMCLICK_GET_NODE_ID: |
604 { | 637 { |
605 // Used only for tracing | 638 // Used only for tracing |
606 NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIM
CLICK_GET_NODE_ID"); | 639 NS_LOG_DEBUG (clickInstance->GetNodeName () << " Received a call for SIM
CLICK_GET_NODE_ID"); |
607 break; | 640 break; |
608 } | 641 } |
609 } | 642 } |
610 return retval; | 643 return retval; |
611 } | 644 } |
612 | 645 |
613 #ifdef __cplusplus | |
614 } | |
615 #endif | |
616 | |
617 #endif // NS3_CLICK | 646 #endif // NS3_CLICK |
LEFT | RIGHT |