A Discrete-Event Network Simulator
API
openflow-switch-net-device.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License version 2 as
4  * published by the Free Software Foundation;
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program; if not, write to the Free Software
13  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14  *
15  * Author: Blake Hurd <naimorai@gmail.com>
16  */
17 #ifdef NS3_OPENFLOW
18 
20 
21 #include "ns3/tcp-l4-protocol.h"
22 #include "ns3/udp-l4-protocol.h"
23 
24 namespace ns3
25 {
26 
27 NS_LOG_COMPONENT_DEFINE("OpenFlowSwitchNetDevice");
28 
29 NS_OBJECT_ENSURE_REGISTERED(OpenFlowSwitchNetDevice);
30 
31 const char*
33 {
34  return "The ns-3 team";
35 }
36 
37 const char*
39 {
40  return "N/A";
41 }
42 
43 const char*
45 {
46  return "Simulated OpenFlow Switch";
47 }
48 
49 const char*
51 {
52  return "N/A";
53 }
54 
55 static uint64_t
56 GenerateId()
57 {
58  uint8_t ea[ETH_ADDR_LEN];
59  eth_addr_random(ea);
60  return eth_addr_to_uint64(ea);
61 }
62 
63 TypeId
65 {
66  static TypeId tid =
67  TypeId("ns3::OpenFlowSwitchNetDevice")
68  .SetParent<NetDevice>()
69  .SetGroupName("Openflow")
71  .AddAttribute("ID",
72  "The identification of the OpenFlowSwitchNetDevice/Datapath, needed for "
73  "OpenFlow compatibility.",
74  UintegerValue(GenerateId()),
76  MakeUintegerChecker<uint64_t>())
77  .AddAttribute("FlowTableLookupDelay",
78  "A real switch will have an overhead for looking up in the flow table. "
79  "For the default, we simulate a standard TCAM on an FPGA.",
80  TimeValue(NanoSeconds(30)),
83  .AddAttribute("Flags", // Note: The Controller can configure this value, overriding the
84  // user's setting.
85  "Flags to turn different functionality on/off, such as whether to inform "
86  "the controller when a flow expires, or how to handle fragments.",
87  UintegerValue(0), // Look at the ofp_config_flags enum in
88  // openflow/include/openflow.h for options.
90  MakeUintegerChecker<uint16_t>())
91  .AddAttribute("FlowTableMissSendLength", // Note: The Controller can configure this
92  // value, overriding the user's setting.
93  "When forwarding a packet the switch didn't match up to the controller, "
94  "it can be more efficient to forward only the first x bytes.",
95  UintegerValue(OFP_DEFAULT_MISS_SEND_LEN), // 128 bytes
97  MakeUintegerChecker<uint16_t>());
98  return tid;
99 }
100 
102  : m_node(nullptr),
103  m_ifIndex(0),
104  m_mtu(0xffff)
105 {
107 
108  m_channel = CreateObject<BridgeChannel>();
109 
110  time_init(); // OFSI's clock; needed to use the buffer storage system.
111  // m_lastTimeout = time_now ();
112 
113  m_controller = nullptr;
114  // m_listenPVConn = 0;
115 
116  m_chain = chain_create();
117  if (!m_chain)
118  {
119  NS_LOG_ERROR("Not enough memory to create the flow table.");
120  }
121 
122  m_ports.reserve(DP_MAX_PORTS);
123  vport_table_init(&m_vportTable);
124 }
125 
126 OpenFlowSwitchNetDevice::~OpenFlowSwitchNetDevice()
127 {
129 }
130 
131 void
132 OpenFlowSwitchNetDevice::DoDispose()
133 {
135 
136  for (Ports_t::iterator b = m_ports.begin(), e = m_ports.end(); b != e; b++)
137  {
138  SendPortStatus(*b, OFPPR_DELETE);
139  b->netdev = nullptr;
140  }
141  m_ports.clear();
142 
143  m_controller = nullptr;
144 
145  chain_destroy(m_chain);
146  RBTreeDestroy(m_vportTable.table);
147  m_channel = nullptr;
148  m_node = nullptr;
149  NetDevice::DoDispose();
150 }
151 
152 void
153 OpenFlowSwitchNetDevice::SetController(Ptr<ofi::Controller> c)
154 {
155  if (m_controller)
156  {
157  NS_LOG_ERROR("Controller already set.");
158  return;
159  }
160 
161  m_controller = c;
162  m_controller->AddSwitch(this);
163 }
164 
165 int
166 OpenFlowSwitchNetDevice::AddSwitchPort(Ptr<NetDevice> switchPort)
167 {
169  NS_ASSERT(switchPort != this);
170  if (!Mac48Address::IsMatchingType(switchPort->GetAddress()))
171  {
172  NS_FATAL_ERROR("Device does not support eui 48 addresses: cannot be added to switch.");
173  }
174  if (!switchPort->SupportsSendFrom())
175  {
176  NS_FATAL_ERROR("Device does not support SendFrom: cannot be added to switch.");
177  }
178  if (m_address == Mac48Address())
179  {
180  m_address = Mac48Address::ConvertFrom(switchPort->GetAddress());
181  }
182 
183  if (m_ports.size() < DP_MAX_PORTS)
184  {
185  ofi::Port p;
186  p.config = 0;
187  p.netdev = switchPort;
188  m_ports.push_back(p);
189 
190  // Notify the controller that this port has been added
191  SendPortStatus(p, OFPPR_ADD);
192 
193  NS_LOG_DEBUG("RegisterProtocolHandler for " << switchPort->GetInstanceTypeId().GetName());
194  m_node->RegisterProtocolHandler(
195  MakeCallback(&OpenFlowSwitchNetDevice::ReceiveFromDevice, this),
196  0,
197  switchPort,
198  true);
199  m_channel->AddChannel(switchPort->GetChannel());
200  }
201  else
202  {
203  return EXFULL;
204  }
205 
206  return 0;
207 }
208 
209 void
210 OpenFlowSwitchNetDevice::SetIfIndex(const uint32_t index)
211 {
213  m_ifIndex = index;
214 }
215 
216 uint32_t
217 OpenFlowSwitchNetDevice::GetIfIndex() const
218 {
220  return m_ifIndex;
221 }
222 
223 Ptr<Channel>
224 OpenFlowSwitchNetDevice::GetChannel() const
225 {
227  return m_channel;
228 }
229 
230 void
231 OpenFlowSwitchNetDevice::SetAddress(Address address)
232 {
234  m_address = Mac48Address::ConvertFrom(address);
235 }
236 
237 Address
238 OpenFlowSwitchNetDevice::GetAddress() const
239 {
241  return m_address;
242 }
243 
244 bool
245 OpenFlowSwitchNetDevice::SetMtu(const uint16_t mtu)
246 {
248  m_mtu = mtu;
249  return true;
250 }
251 
252 uint16_t
253 OpenFlowSwitchNetDevice::GetMtu() const
254 {
256  return m_mtu;
257 }
258 
259 bool
260 OpenFlowSwitchNetDevice::IsLinkUp() const
261 {
263  return true;
264 }
265 
266 void
267 OpenFlowSwitchNetDevice::AddLinkChangeCallback(Callback<void> callback)
268 {
269 }
270 
271 bool
272 OpenFlowSwitchNetDevice::IsBroadcast() const
273 {
275  return true;
276 }
277 
278 Address
279 OpenFlowSwitchNetDevice::GetBroadcast() const
280 {
282  return Mac48Address("ff:ff:ff:ff:ff:ff");
283 }
284 
285 bool
287 {
289  return true;
290 }
291 
292 Address
293 OpenFlowSwitchNetDevice::GetMulticast(Ipv4Address multicastGroup) const
294 {
295  NS_LOG_FUNCTION(this << multicastGroup);
296  Mac48Address multicast = Mac48Address::GetMulticast(multicastGroup);
297  return multicast;
298 }
299 
300 bool
301 OpenFlowSwitchNetDevice::IsPointToPoint() const
302 {
304  return false;
305 }
306 
307 bool
308 OpenFlowSwitchNetDevice::IsBridge() const
309 {
311  return true;
312 }
313 
314 void
315 OpenFlowSwitchNetDevice::DoOutput(uint32_t packet_uid,
316  int in_port,
317  size_t max_len,
318  int out_port,
319  bool ignore_no_fwd)
320 {
321  if (out_port != OFPP_CONTROLLER)
322  {
323  OutputPort(packet_uid, in_port, out_port, ignore_no_fwd);
324  }
325  else
326  {
327  OutputControl(packet_uid, in_port, max_len, OFPR_ACTION);
328  }
329 }
330 
331 bool
332 OpenFlowSwitchNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
333 {
335  return SendFrom(packet, m_address, dest, protocolNumber);
336 }
337 
338 bool
339 OpenFlowSwitchNetDevice::SendFrom(Ptr<Packet> packet,
340  const Address& src,
341  const Address& dest,
342  uint16_t protocolNumber)
343 {
345 
346  ofpbuf* buffer = BufferFromPacket(packet, src, dest, GetMtu(), protocolNumber);
347 
348  uint32_t packet_uid = save_buffer(buffer);
349  ofi::SwitchPacketMetadata data;
350  data.packet = packet;
351  data.buffer = buffer;
352  data.protocolNumber = protocolNumber;
353  data.src = Address(src);
354  data.dst = Address(dest);
355  m_packetData.insert(std::make_pair(packet_uid, data));
356 
357  RunThroughFlowTable(packet_uid, -1);
358 
359  return true;
360 }
361 
362 Ptr<Node>
363 OpenFlowSwitchNetDevice::GetNode() const
364 {
366  return m_node;
367 }
368 
369 void
370 OpenFlowSwitchNetDevice::SetNode(Ptr<Node> node)
371 {
373  m_node = node;
374 }
375 
376 bool
377 OpenFlowSwitchNetDevice::NeedsArp() const
378 {
380  return true;
381 }
382 
383 void
384 OpenFlowSwitchNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb)
385 {
387  m_rxCallback = cb;
388 }
389 
390 void
391 OpenFlowSwitchNetDevice::SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
392 {
394  m_promiscRxCallback = cb;
395 }
396 
397 bool
398 OpenFlowSwitchNetDevice::SupportsSendFrom() const
399 {
401  return true;
402 }
403 
404 Address
405 OpenFlowSwitchNetDevice::GetMulticast(Ipv6Address addr) const
406 {
407  NS_LOG_FUNCTION(this << addr);
408  return Mac48Address::GetMulticast(addr);
409 }
410 
411 // Add a virtual port table entry.
412 int
413 OpenFlowSwitchNetDevice::AddVPort(const ofp_vport_mod* ovpm)
414 {
415  size_t actions_len = ntohs(ovpm->header.length) - sizeof *ovpm;
416  unsigned int vport = ntohl(ovpm->vport);
417  unsigned int parent_port = ntohl(ovpm->parent_port);
418 
419  // check whether port table entry exists for specified port number
420  vport_table_entry* vpe = vport_table_lookup(&m_vportTable, vport);
421  if (vpe)
422  {
423  NS_LOG_ERROR("vport " << vport << " already exists!");
424  SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
425  return EINVAL;
426  }
427 
428  // check whether actions are valid
429  uint16_t v_code = ofi::ValidateVPortActions(ovpm->actions, actions_len);
430  if (v_code != ACT_VALIDATION_OK)
431  {
432  SendErrorMsg(OFPET_BAD_ACTION, v_code, ovpm, ntohs(ovpm->header.length));
433  return EINVAL;
434  }
435 
436  vpe = vport_table_entry_alloc(actions_len);
437 
438  vpe->vport = vport;
439  vpe->parent_port = parent_port;
440  if (vport < OFPP_VP_START || vport > OFPP_VP_END)
441  {
442  NS_LOG_ERROR("port " << vport << " is not in the virtual port range (" << OFPP_VP_START
443  << "-" << OFPP_VP_END << ")");
444  SendErrorMsg(OFPET_BAD_ACTION, OFPET_VPORT_MOD_FAILED, ovpm, ntohs(ovpm->header.length));
445  free_vport_table_entry(vpe); // free allocated entry
446  return EINVAL;
447  }
448 
449  vpe->port_acts->actions_len = actions_len;
450  memcpy(vpe->port_acts->actions, ovpm->actions, actions_len);
451 
452  int error = insert_vport_table_entry(&m_vportTable, vpe);
453  if (error)
454  {
455  NS_LOG_ERROR("could not insert port table entry for port " << vport);
456  }
457 
458  return error;
459 }
460 
461 ofpbuf*
462 OpenFlowSwitchNetDevice::BufferFromPacket(Ptr<const Packet> constPacket,
463  Address src,
464  Address dst,
465  int mtu,
466  uint16_t protocol)
467 {
468  NS_LOG_INFO("Creating Openflow buffer from packet.");
469 
470  Ptr<Packet> packet = constPacket->Copy();
471  /*
472  * Allocate buffer with some headroom to add headers in forwarding
473  * to the controller or adding a vlan tag, plus an extra 2 bytes to
474  * allow IP headers to be aligned on a 4-byte boundary.
475  */
476  const int headroom = 128 + 2;
477  const int hard_header = VLAN_ETH_HEADER_LEN;
478  ofpbuf* buffer = ofpbuf_new(headroom + hard_header + mtu);
479  buffer->data = (char*)buffer->data + headroom + hard_header;
480 
481  int l2_length = 0;
482  int l3_length = 0;
483  int l4_length = 0;
484 
485  // Parse Ethernet header
486  buffer->l2 = new eth_header;
487  eth_header* eth_h = (eth_header*)buffer->l2;
488  dst.CopyTo(eth_h->eth_dst); // Destination Mac Address
489  src.CopyTo(eth_h->eth_src); // Source Mac Address
490  if (protocol == ArpL3Protocol::PROT_NUMBER)
491  {
492  eth_h->eth_type = htons(ETH_TYPE_ARP); // Ether Type
493  }
494  else if (protocol == Ipv4L3Protocol::PROT_NUMBER)
495  {
496  eth_h->eth_type = htons(ETH_TYPE_IP); // Ether Type
497  }
498  else
499  {
500  NS_LOG_WARN("Protocol unsupported: " << protocol);
501  }
502  NS_LOG_INFO("Parsed EthernetHeader");
503 
504  l2_length = ETH_HEADER_LEN;
505 
506  // We have to wrap this because PeekHeader has an assert fail if we check for an Ipv4Header that
507  // isn't there.
508  if (protocol == Ipv4L3Protocol::PROT_NUMBER)
509  {
510  Ipv4Header ip_hd;
511  if (packet->PeekHeader(ip_hd))
512  {
513  buffer->l3 = new ip_header;
514  ip_header* ip_h = (ip_header*)buffer->l3;
515  ip_h->ip_ihl_ver = IP_IHL_VER(5, IP_VERSION); // Version
516  ip_h->ip_tos = ip_hd.GetTos(); // Type of Service/Differentiated Services
517  ip_h->ip_tot_len = packet->GetSize(); // Total Length
518  ip_h->ip_id = ip_hd.GetIdentification(); // Identification
519  ip_h->ip_frag_off = ip_hd.GetFragmentOffset(); // Fragment Offset
520  ip_h->ip_ttl = ip_hd.GetTtl(); // Time to Live
521  ip_h->ip_proto = ip_hd.GetProtocol(); // Protocol
522  ip_h->ip_src = htonl(ip_hd.GetSource().Get()); // Source Address
523  ip_h->ip_dst = htonl(ip_hd.GetDestination().Get()); // Destination Address
524  ip_h->ip_csum = csum(&ip_h, sizeof ip_h); // Header Checksum
525  NS_LOG_INFO("Parsed Ipv4Header");
526  packet->RemoveHeader(ip_hd);
527 
528  l3_length = IP_HEADER_LEN;
529  }
530  }
531  else
532  {
533  // ARP Packet; the underlying OpenFlow header isn't used to match, so this is probably
534  // superfluous.
535  ArpHeader arp_hd;
536  if (packet->PeekHeader(arp_hd))
537  {
538  buffer->l3 = new arp_eth_header;
539  arp_eth_header* arp_h = (arp_eth_header*)buffer->l3;
540  arp_h->ar_hrd = ARP_HRD_ETHERNET; // Hardware type.
541  arp_h->ar_pro = ARP_PRO_IP; // Protocol type.
542  arp_h->ar_op = arp_hd.m_type; // Opcode.
543  arp_hd.GetDestinationHardwareAddress().CopyTo(
544  arp_h->ar_tha); // Target hardware address.
545  arp_hd.GetSourceHardwareAddress().CopyTo(arp_h->ar_sha); // Sender hardware address.
546  arp_h->ar_tpa = arp_hd.GetDestinationIpv4Address().Get(); // Target protocol address.
547  arp_h->ar_spa = arp_hd.GetSourceIpv4Address().Get(); // Sender protocol address.
548  arp_h->ar_hln = sizeof arp_h->ar_tha; // Hardware address length.
549  arp_h->ar_pln = sizeof arp_h->ar_tpa; // Protocol address length.
550  NS_LOG_INFO("Parsed ArpHeader");
551  packet->RemoveHeader(arp_hd);
552 
553  l3_length = ARP_ETH_HEADER_LEN;
554  }
555  }
556 
557  if (protocol == Ipv4L3Protocol::PROT_NUMBER)
558  {
559  ip_header* ip_h = (ip_header*)buffer->l3;
560  if (ip_h->ip_proto == TcpL4Protocol::PROT_NUMBER)
561  {
562  TcpHeader tcp_hd;
563  if (packet->PeekHeader(tcp_hd))
564  {
565  buffer->l4 = new tcp_header;
566  tcp_header* tcp_h = (tcp_header*)buffer->l4;
567  tcp_h->tcp_src = htons(tcp_hd.GetSourcePort()); // Source Port
568  tcp_h->tcp_dst = htons(tcp_hd.GetDestinationPort()); // Destination Port
569  tcp_h->tcp_seq = tcp_hd.GetSequenceNumber().GetValue(); // Sequence Number
570  tcp_h->tcp_ack = tcp_hd.GetAckNumber().GetValue(); // ACK Number
571  tcp_h->tcp_ctl = TCP_FLAGS(tcp_hd.GetFlags()); // Data Offset + Reserved + Flags
572  tcp_h->tcp_winsz = tcp_hd.GetWindowSize(); // Window Size
573  tcp_h->tcp_urg = tcp_hd.GetUrgentPointer(); // Urgent Pointer
574  tcp_h->tcp_csum = csum(&tcp_h, sizeof tcp_h); // Header Checksum
575  NS_LOG_INFO("Parsed TcpHeader");
576  packet->RemoveHeader(tcp_hd);
577 
578  l4_length = TCP_HEADER_LEN;
579  }
580  }
581  else if (ip_h->ip_proto == UdpL4Protocol::PROT_NUMBER)
582  {
583  UdpHeader udp_hd;
584  if (packet->PeekHeader(udp_hd))
585  {
586  buffer->l4 = new udp_header;
587  udp_header* udp_h = (udp_header*)buffer->l4;
588  udp_h->udp_src = htons(udp_hd.GetSourcePort()); // Source Port
589  udp_h->udp_dst = htons(udp_hd.GetDestinationPort()); // Destination Port
590  udp_h->udp_len = htons(UDP_HEADER_LEN + packet->GetSize());
591 
592  ip_header* ip_h = (ip_header*)buffer->l3;
593  uint32_t udp_csum = csum_add32(0, ip_h->ip_src);
594  udp_csum = csum_add32(udp_csum, ip_h->ip_dst);
595  udp_csum = csum_add16(udp_csum, IP_TYPE_UDP << 8);
596  udp_csum = csum_add16(udp_csum, udp_h->udp_len);
597  udp_csum = csum_continue(udp_csum, udp_h, sizeof udp_h);
598  udp_h->udp_csum = csum_finish(
599  csum_continue(udp_csum, buffer->data, buffer->size)); // Header Checksum
600  NS_LOG_INFO("Parsed UdpHeader");
601  packet->RemoveHeader(udp_hd);
602 
603  l4_length = UDP_HEADER_LEN;
604  }
605  }
606  }
607 
608  // Load any remaining packet data into buffer data
609  packet->CopyData((uint8_t*)buffer->data, packet->GetSize());
610 
611  if (buffer->l4)
612  {
613  ofpbuf_push(buffer, buffer->l4, l4_length);
614  delete (tcp_header*)buffer->l4;
615  }
616  if (buffer->l3)
617  {
618  ofpbuf_push(buffer, buffer->l3, l3_length);
619  delete (ip_header*)buffer->l3;
620  }
621  if (buffer->l2)
622  {
623  ofpbuf_push(buffer, buffer->l2, l2_length);
624  delete (eth_header*)buffer->l2;
625  }
626 
627  return buffer;
628 }
629 
630 void
631 OpenFlowSwitchNetDevice::ReceiveFromDevice(Ptr<NetDevice> netdev,
632  Ptr<const Packet> packet,
633  uint16_t protocol,
634  const Address& src,
635  const Address& dst,
636  PacketType packetType)
637 {
639  NS_LOG_INFO("--------------------------------------------");
640  NS_LOG_DEBUG("UID is " << packet->GetUid());
641 
642  if (!m_promiscRxCallback.IsNull())
643  {
644  m_promiscRxCallback(this, packet, protocol, src, dst, packetType);
645  }
646 
647  Mac48Address dst48 = Mac48Address::ConvertFrom(dst);
648  NS_LOG_INFO("Received packet from " << Mac48Address::ConvertFrom(src) << " looking for "
649  << dst48);
650 
651  for (size_t i = 0; i < m_ports.size(); i++)
652  {
653  if (m_ports[i].netdev == netdev)
654  {
655  if (packetType == PACKET_HOST && dst48 == m_address)
656  {
657  m_rxCallback(this, packet, protocol, src);
658  }
659  else if (packetType == PACKET_BROADCAST || packetType == PACKET_MULTICAST ||
660  packetType == PACKET_OTHERHOST)
661  {
662  if (packetType == PACKET_OTHERHOST && dst48 == m_address)
663  {
664  m_rxCallback(this, packet, protocol, src);
665  }
666  else
667  {
668  if (packetType != PACKET_OTHERHOST)
669  {
670  m_rxCallback(this, packet, protocol, src);
671  }
672 
673  ofi::SwitchPacketMetadata data;
674  data.packet = packet->Copy();
675 
676  ofpbuf* buffer =
677  BufferFromPacket(data.packet, src, dst, netdev->GetMtu(), protocol);
678  m_ports[i].rx_packets++;
679  m_ports[i].rx_bytes += buffer->size;
680  data.buffer = buffer;
681  uint32_t packet_uid = save_buffer(buffer);
682 
683  data.protocolNumber = protocol;
684  data.src = Address(src);
685  data.dst = Address(dst);
686  m_packetData.insert(std::make_pair(packet_uid, data));
687 
688  RunThroughFlowTable(packet_uid, i);
689  }
690  }
691 
692  break;
693  }
694  }
695 
696  // Run periodic execution.
697  Time now = Simulator::Now();
698  if (now >= Seconds(m_lastExecute.GetSeconds() +
699  1)) // If a second or more has passed from the simulation time, execute.
700  {
701  // If port status is modified in any way, notify the controller.
702  for (size_t i = 0; i < m_ports.size(); i++)
703  {
704  if (UpdatePortStatus(m_ports[i]))
705  {
706  SendPortStatus(m_ports[i], OFPPR_MODIFY);
707  }
708  }
709 
710  // If any flows have expired, delete them and notify the controller.
711  List deleted = LIST_INITIALIZER(&deleted);
712  sw_flow* f;
713  sw_flow* n;
714  chain_timeout(m_chain, &deleted);
715  LIST_FOR_EACH_SAFE(f, n, sw_flow, node, &deleted)
716  {
717  std::ostringstream str;
718  str << "Flow [";
719  for (int i = 0; i < 6; i++)
720  {
721  str << (i != 0 ? ":" : "") << std::hex << f->key.flow.dl_src[i] / 16
722  << f->key.flow.dl_src[i] % 16;
723  }
724  str << " -> ";
725  for (int i = 0; i < 6; i++)
726  {
727  str << (i != 0 ? ":" : "") << std::hex << f->key.flow.dl_dst[i] / 16
728  << f->key.flow.dl_dst[i] % 16;
729  }
730  str << "] expired.";
731 
732  NS_LOG_INFO(str.str());
733  SendFlowExpired(f, (ofp_flow_expired_reason)f->reason);
734  list_remove(&f->node);
735  flow_free(f);
736  }
737 
738  m_lastExecute = now;
739  }
740 }
741 
742 int
743 OpenFlowSwitchNetDevice::OutputAll(uint32_t packet_uid, int in_port, bool flood)
744 {
746  NS_LOG_INFO("Flooding over ports.");
747 
748  int prev_port = -1;
749  for (size_t i = 0; i < m_ports.size(); i++)
750  {
751  if (i == (unsigned)in_port) // Originating port
752  {
753  continue;
754  }
755  if (flood && m_ports[i].config & OFPPC_NO_FLOOD) // Port configured to not allow flooding
756  {
757  continue;
758  }
759  if (prev_port != -1)
760  {
761  OutputPort(packet_uid, in_port, prev_port, false);
762  }
763  prev_port = i;
764  }
765  if (prev_port != -1)
766  {
767  OutputPort(packet_uid, in_port, prev_port, false);
768  }
769 
770  return 0;
771 }
772 
773 void
774 OpenFlowSwitchNetDevice::OutputPacket(uint32_t packet_uid, int out_port)
775 {
776  if (out_port >= 0 && out_port < DP_MAX_PORTS)
777  {
778  ofi::Port& p = m_ports[out_port];
779  if (p.netdev && !(p.config & OFPPC_PORT_DOWN))
780  {
781  ofi::SwitchPacketMetadata data = m_packetData.find(packet_uid)->second;
782  size_t bufsize = data.buffer->size;
783  NS_LOG_INFO("Sending packet " << data.packet->GetUid() << " over port " << out_port);
784  if (p.netdev->SendFrom(data.packet->Copy(), data.src, data.dst, data.protocolNumber))
785  {
786  p.tx_packets++;
787  p.tx_bytes += bufsize;
788  }
789  else
790  {
791  p.tx_dropped++;
792  }
793  return;
794  }
795  }
796 
797  NS_LOG_DEBUG("can't forward to bad port " << out_port);
798 }
799 
800 void
801 OpenFlowSwitchNetDevice::OutputPort(uint32_t packet_uid,
802  int in_port,
803  int out_port,
804  bool ignore_no_fwd)
805 {
807 
808  if (out_port == OFPP_FLOOD)
809  {
810  OutputAll(packet_uid, in_port, true);
811  }
812  else if (out_port == OFPP_ALL)
813  {
814  OutputAll(packet_uid, in_port, false);
815  }
816  else if (out_port == OFPP_CONTROLLER)
817  {
818  OutputControl(packet_uid, in_port, 0, OFPR_ACTION);
819  }
820  else if (out_port == OFPP_IN_PORT)
821  {
822  OutputPacket(packet_uid, in_port);
823  }
824  else if (out_port == OFPP_TABLE)
825  {
826  RunThroughFlowTable(packet_uid, in_port < DP_MAX_PORTS ? in_port : -1, false);
827  }
828  else if (out_port >= OFPP_VP_START && out_port <= OFPP_VP_END)
829  {
830  // port is a virtual port
831  NS_LOG_INFO("packet sent to virtual port " << out_port);
832  if (in_port < DP_MAX_PORTS)
833  {
834  RunThroughVPortTable(packet_uid, in_port, out_port);
835  }
836  else
837  {
838  RunThroughVPortTable(packet_uid, -1, out_port);
839  }
840  }
841  else if (in_port == out_port)
842  {
843  NS_LOG_DEBUG("can't directly forward to input port");
844  }
845  else
846  {
847  OutputPacket(packet_uid, out_port);
848  }
849 }
850 
851 void*
852 OpenFlowSwitchNetDevice::MakeOpenflowReply(size_t openflow_len, uint8_t type, ofpbuf** bufferp)
853 {
854  return make_openflow_xid(openflow_len, type, 0, bufferp);
855 }
856 
857 int
858 OpenFlowSwitchNetDevice::SendOpenflowBuffer(ofpbuf* buffer)
859 {
860  if (m_controller)
861  {
862  update_openflow_length(buffer);
863  m_controller->ReceiveFromSwitch(this, buffer);
864  }
865 
866  return 0;
867 }
868 
869 void
870 OpenFlowSwitchNetDevice::OutputControl(uint32_t packet_uid, int in_port, size_t max_len, int reason)
871 {
872  NS_LOG_INFO("Sending packet to controller");
873 
874  ofpbuf* buffer = m_packetData.find(packet_uid)->second.buffer;
875  size_t total_len = buffer->size;
876  if (packet_uid != std::numeric_limits<uint32_t>::max() && max_len != 0 &&
877  buffer->size > max_len)
878  {
879  buffer->size = max_len;
880  }
881 
882  ofp_packet_in* opi = (ofp_packet_in*)ofpbuf_push_uninit(buffer, offsetof(ofp_packet_in, data));
883  opi->header.version = OFP_VERSION;
884  opi->header.type = OFPT_PACKET_IN;
885  opi->header.length = htons(buffer->size);
886  opi->header.xid = htonl(0);
887  opi->buffer_id = htonl(packet_uid);
888  opi->total_len = htons(total_len);
889  opi->in_port = htons(in_port);
890  opi->reason = reason;
891  opi->pad = 0;
892  SendOpenflowBuffer(buffer);
893 }
894 
895 void
896 OpenFlowSwitchNetDevice::FillPortDesc(ofi::Port p, ofp_phy_port* desc)
897 {
898  desc->port_no = htons(GetSwitchPortIndex(p));
899 
900  std::ostringstream nm;
901  nm << "eth" << GetSwitchPortIndex(p);
902  strncpy((char*)desc->name, nm.str().c_str(), sizeof desc->name);
903 
904  p.netdev->GetAddress().CopyTo(desc->hw_addr);
905  desc->config = htonl(p.config);
906  desc->state = htonl(p.state);
907 
909  desc->curr = 0; // htonl(netdev_get_features(p->netdev, NETDEV_FEAT_CURRENT));
910  desc->supported = 0; // htonl(netdev_get_features(p->netdev, NETDEV_FEAT_SUPPORTED));
911  desc->advertised = 0; // htonl(netdev_get_features(p->netdev, NETDEV_FEAT_ADVERTISED));
912  desc->peer = 0; // htonl(netdev_get_features(p->netdev, NETDEV_FEAT_PEER));
913 }
914 
915 void
916 OpenFlowSwitchNetDevice::SendFeaturesReply()
917 {
918  ofpbuf* buffer;
919  ofp_switch_features* ofr =
920  (ofp_switch_features*)MakeOpenflowReply(sizeof *ofr, OFPT_FEATURES_REPLY, &buffer);
921  ofr->datapath_id = htonll(m_id);
922  ofr->n_tables = m_chain->n_tables;
923  ofr->n_buffers = htonl(N_PKT_BUFFERS);
924  ofr->capabilities = htonl(OFP_SUPPORTED_CAPABILITIES);
925  ofr->actions = htonl(OFP_SUPPORTED_ACTIONS);
926 
927  for (size_t i = 0; i < m_ports.size(); i++)
928  {
929  ofp_phy_port* opp = (ofp_phy_port*)ofpbuf_put_zeros(buffer, sizeof *opp);
930  FillPortDesc(m_ports[i], opp);
931  }
932 
933  SendOpenflowBuffer(buffer);
934 }
935 
936 void
937 OpenFlowSwitchNetDevice::SendVPortTableFeatures()
938 {
939  ofpbuf* buffer;
940  ofp_vport_table_features* ovtfr =
941  (ofp_vport_table_features*)MakeOpenflowReply(sizeof *ovtfr,
942  OFPT_VPORT_TABLE_FEATURES_REPLY,
943  &buffer);
944  ovtfr->actions = htonl(OFP_SUPPORTED_VPORT_TABLE_ACTIONS);
945  ovtfr->max_vports = htonl(m_vportTable.max_vports);
946  ovtfr->max_chain_depth = htons(-1); // support a chain depth of 2^16
947  ovtfr->mixed_chaining = true;
948  SendOpenflowBuffer(buffer);
949 }
950 
951 int
952 OpenFlowSwitchNetDevice::UpdatePortStatus(ofi::Port& p)
953 {
954  uint32_t orig_config = p.config;
955  uint32_t orig_state = p.state;
956 
957  // Port is always enabled because the Net Device is always enabled.
958  p.config &= ~OFPPC_PORT_DOWN;
959 
960  if (p.netdev->IsLinkUp())
961  {
962  p.state &= ~OFPPS_LINK_DOWN;
963  }
964  else
965  {
966  p.state |= OFPPS_LINK_DOWN;
967  }
968 
969  return ((orig_config != p.config) || (orig_state != p.state));
970 }
971 
972 void
973 OpenFlowSwitchNetDevice::SendPortStatus(ofi::Port p, uint8_t status)
974 {
975  ofpbuf* buffer;
976  ofp_port_status* ops =
977  (ofp_port_status*)MakeOpenflowReply(sizeof *ops, OFPT_PORT_STATUS, &buffer);
978  ops->reason = status;
979  memset(ops->pad, 0, sizeof ops->pad);
980  FillPortDesc(p, &ops->desc);
981 
982  SendOpenflowBuffer(buffer);
983  ofpbuf_delete(buffer);
984 }
985 
986 void
987 OpenFlowSwitchNetDevice::SendFlowExpired(sw_flow* flow, enum ofp_flow_expired_reason reason)
988 {
989  ofpbuf* buffer;
990  ofp_flow_expired* ofe =
991  (ofp_flow_expired*)MakeOpenflowReply(sizeof *ofe, OFPT_FLOW_EXPIRED, &buffer);
992  flow_fill_match(&ofe->match, &flow->key);
993 
994  ofe->priority = htons(flow->priority);
995  ofe->reason = reason;
996  memset(ofe->pad, 0, sizeof ofe->pad);
997 
998  ofe->duration = htonl(time_now() - flow->created);
999  memset(ofe->pad2, 0, sizeof ofe->pad2);
1000  ofe->packet_count = htonll(flow->packet_count);
1001  ofe->byte_count = htonll(flow->byte_count);
1002  SendOpenflowBuffer(buffer);
1003 }
1004 
1005 void
1006 OpenFlowSwitchNetDevice::SendErrorMsg(uint16_t type, uint16_t code, const void* data, size_t len)
1007 {
1008  ofpbuf* buffer;
1009  ofp_error_msg* oem = (ofp_error_msg*)MakeOpenflowReply(sizeof(*oem) + len, OFPT_ERROR, &buffer);
1010  oem->type = htons(type);
1011  oem->code = htons(code);
1012  memcpy(oem->data, data, len);
1013  SendOpenflowBuffer(buffer);
1014 }
1015 
1016 void
1017 OpenFlowSwitchNetDevice::FlowTableLookup(sw_flow_key key,
1018  ofpbuf* buffer,
1019  uint32_t packet_uid,
1020  int port,
1021  bool send_to_controller)
1022 {
1023  sw_flow* flow = chain_lookup(m_chain, &key);
1024  if (flow)
1025  {
1026  NS_LOG_INFO("Flow matched");
1027  flow_used(flow, buffer);
1028  ofi::ExecuteActions(this,
1029  packet_uid,
1030  buffer,
1031  &key,
1032  flow->sf_acts->actions,
1033  flow->sf_acts->actions_len,
1034  false);
1035  }
1036  else
1037  {
1038  NS_LOG_INFO("Flow not matched.");
1039 
1040  if (send_to_controller)
1041  {
1042  OutputControl(packet_uid, port, m_missSendLen, OFPR_NO_MATCH);
1043  }
1044  }
1045 
1046  // Clean up; at this point we're done with the packet.
1047  m_packetData.erase(packet_uid);
1048  discard_buffer(packet_uid);
1049  ofpbuf_delete(buffer);
1050 }
1051 
1052 void
1053 OpenFlowSwitchNetDevice::RunThroughFlowTable(uint32_t packet_uid, int port, bool send_to_controller)
1054 {
1055  ofi::SwitchPacketMetadata data = m_packetData.find(packet_uid)->second;
1056  ofpbuf* buffer = data.buffer;
1057 
1058  sw_flow_key key;
1059  key.wildcards = 0; // Lookup cannot take wildcards.
1060  // Extract the matching key's flow data from the packet's headers; if the policy is to drop
1061  // fragments and the message is a fragment, drop it.
1062  if (flow_extract(buffer, port != -1 ? port : OFPP_NONE, &key.flow) &&
1063  (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1064  {
1065  ofpbuf_delete(buffer);
1066  return;
1067  }
1068 
1069  // drop MPLS packets with TTL 1
1070  if (buffer->l2_5)
1071  {
1072  mpls_header mpls_h;
1073  mpls_h.value = ntohl(*((uint32_t*)buffer->l2_5));
1074  if (mpls_h.ttl == 1)
1075  {
1076  // increment mpls drop counter
1077  if (port != -1)
1078  {
1079  m_ports[port].mpls_ttl0_dropped++;
1080  }
1081  return;
1082  }
1083  }
1084 
1085  // If we received the packet on a port, and opted not to receive any messages from it...
1086  if (port != -1)
1087  {
1088  uint32_t config = m_ports[port].config;
1089  if (config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
1090  config & (!eth_addr_equals(key.flow.dl_dst, stp_eth_addr) ? OFPPC_NO_RECV
1091  : OFPPC_NO_RECV_STP))
1092  {
1093  return;
1094  }
1095  }
1096 
1097  NS_LOG_INFO("Matching against the flow table.");
1098  Simulator::Schedule(m_lookupDelay,
1099  &OpenFlowSwitchNetDevice::FlowTableLookup,
1100  this,
1101  key,
1102  buffer,
1103  packet_uid,
1104  port,
1105  send_to_controller);
1106 }
1107 
1108 int
1109 OpenFlowSwitchNetDevice::RunThroughVPortTable(uint32_t packet_uid, int port, uint32_t vport)
1110 {
1111  ofpbuf* buffer = m_packetData.find(packet_uid)->second.buffer;
1112 
1113  // extract the flow again since we need it
1114  // and the layer pointers may changed
1115  sw_flow_key key;
1116  key.wildcards = 0;
1117  if (flow_extract(buffer, port != -1 ? port : OFPP_NONE, &key.flow) &&
1118  (m_flags & OFPC_FRAG_MASK) == OFPC_FRAG_DROP)
1119  {
1120  return 0;
1121  }
1122 
1123  // run through the chain of port table entries
1124  vport_table_entry* vpe = vport_table_lookup(&m_vportTable, vport);
1125  m_vportTable.lookup_count++;
1126  if (vpe)
1127  {
1128  m_vportTable.port_match_count++;
1129  }
1130  while (vpe)
1131  {
1133  packet_uid,
1134  m_packetData.find(packet_uid)->second.buffer,
1135  &key,
1136  vpe->port_acts->actions,
1137  vpe->port_acts->actions_len);
1138  vport_used(vpe, buffer); // update counters for virtual port
1139  if (!vpe->parent_port_ptr)
1140  {
1141  // if a port table's parent_port_ptr is 0 then
1142  // the parent_port should be a physical port
1143  if (vpe->parent_port <=
1144  OFPP_VP_START) // done traversing port chain, send packet to output port
1145  {
1146  OutputPort(packet_uid, port != -1 ? port : OFPP_NONE, vpe->parent_port, false);
1147  }
1148  else
1149  {
1150  NS_LOG_ERROR("virtual port points to parent port\n");
1151  }
1152  }
1153  else // increment the number of port entries accessed by chaining
1154  {
1155  m_vportTable.chain_match_count++;
1156  }
1157  // move to the parent port entry
1158  vpe = vpe->parent_port_ptr;
1159  }
1160 
1161  return 0;
1162 }
1163 
1164 int
1165 OpenFlowSwitchNetDevice::ReceiveFeaturesRequest(const void* msg)
1166 {
1167  SendFeaturesReply();
1168  return 0;
1169 }
1170 
1171 int
1172 OpenFlowSwitchNetDevice::ReceiveVPortTableFeaturesRequest(const void* msg)
1173 {
1174  SendVPortTableFeatures();
1175  return 0;
1176 }
1177 
1178 int
1179 OpenFlowSwitchNetDevice::ReceiveGetConfigRequest(const void* msg)
1180 {
1181  ofpbuf* buffer;
1182  ofp_switch_config* osc =
1183  (ofp_switch_config*)MakeOpenflowReply(sizeof *osc, OFPT_GET_CONFIG_REPLY, &buffer);
1184  osc->flags = htons(m_flags);
1185  osc->miss_send_len = htons(m_missSendLen);
1186 
1187  return SendOpenflowBuffer(buffer);
1188 }
1189 
1190 int
1191 OpenFlowSwitchNetDevice::ReceiveSetConfig(const void* msg)
1192 {
1193  const ofp_switch_config* osc = (ofp_switch_config*)msg;
1194 
1195  int n_flags = ntohs(osc->flags) & (OFPC_SEND_FLOW_EXP | OFPC_FRAG_MASK);
1196  if ((n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_NORMAL &&
1197  (n_flags & OFPC_FRAG_MASK) != OFPC_FRAG_DROP)
1198  {
1199  n_flags = (n_flags & ~OFPC_FRAG_MASK) | OFPC_FRAG_DROP;
1200  }
1201 
1202  m_flags = n_flags;
1203  m_missSendLen = ntohs(osc->miss_send_len);
1204  return 0;
1205 }
1206 
1207 int
1208 OpenFlowSwitchNetDevice::ReceivePacketOut(const void* msg)
1209 {
1210  const ofp_packet_out* opo = (ofp_packet_out*)msg;
1211  ofpbuf* buffer;
1212  size_t actions_len = ntohs(opo->actions_len);
1213 
1214  if (actions_len > (ntohs(opo->header.length) - sizeof *opo))
1215  {
1216  NS_LOG_DEBUG("message too short for number of actions");
1217  return -EINVAL;
1218  }
1219 
1220  if (ntohl(opo->buffer_id) == (uint32_t)-1)
1221  {
1222  // FIXME: can we avoid copying data here?
1223  int data_len = ntohs(opo->header.length) - sizeof *opo - actions_len;
1224  buffer = ofpbuf_new(data_len);
1225  ofpbuf_put(buffer, (uint8_t*)opo->actions + actions_len, data_len);
1226  }
1227  else
1228  {
1229  buffer = retrieve_buffer(ntohl(opo->buffer_id));
1230  if (!buffer)
1231  {
1232  return -ESRCH;
1233  }
1234  }
1235 
1236  sw_flow_key key;
1237  flow_extract(buffer, ntohs(opo->in_port), &key.flow); // ntohs(opo->in_port)
1238 
1239  uint16_t v_code = ofi::ValidateActions(&key, opo->actions, actions_len);
1240  if (v_code != ACT_VALIDATION_OK)
1241  {
1242  SendErrorMsg(OFPET_BAD_ACTION, v_code, msg, ntohs(opo->header.length));
1243  ofpbuf_delete(buffer);
1244  return -EINVAL;
1245  }
1246 
1247  ofi::ExecuteActions(this, opo->buffer_id, buffer, &key, opo->actions, actions_len, true);
1248  return 0;
1249 }
1250 
1251 int
1252 OpenFlowSwitchNetDevice::ReceivePortMod(const void* msg)
1253 {
1254  ofp_port_mod* opm = (ofp_port_mod*)msg;
1255 
1256  int port = opm->port_no; // ntohs(opm->port_no);
1257  if (port < DP_MAX_PORTS)
1258  {
1259  ofi::Port& p = m_ports[port];
1260 
1261  // Make sure the port id hasn't changed since this was sent
1262  Mac48Address hw_addr = Mac48Address();
1263  hw_addr.CopyFrom(opm->hw_addr);
1264  if (p.netdev->GetAddress() != hw_addr)
1265  {
1266  return 0;
1267  }
1268 
1269  if (opm->mask)
1270  {
1271  uint32_t config_mask = ntohl(opm->mask);
1272  p.config &= ~config_mask;
1273  p.config |= ntohl(opm->config) & config_mask;
1274  }
1275 
1276  if (opm->mask & htonl(OFPPC_PORT_DOWN))
1277  {
1278  if ((opm->config & htonl(OFPPC_PORT_DOWN)) && (p.config & OFPPC_PORT_DOWN) == 0)
1279  {
1280  p.config |= OFPPC_PORT_DOWN;
1282  }
1283  else if ((opm->config & htonl(OFPPC_PORT_DOWN)) == 0 && (p.config & OFPPC_PORT_DOWN))
1284  {
1285  p.config &= ~OFPPC_PORT_DOWN;
1287  }
1288  }
1289  }
1290 
1291  return 0;
1292 }
1293 
1294 // add or remove a virtual port table entry
1295 int
1296 OpenFlowSwitchNetDevice::ReceiveVPortMod(const void* msg)
1297 {
1298  const ofp_vport_mod* ovpm = (ofp_vport_mod*)msg;
1299 
1300  uint16_t command = ntohs(ovpm->command);
1301  if (command == OFPVP_ADD)
1302  {
1303  return AddVPort(ovpm);
1304  }
1305  else if (command == OFPVP_DELETE)
1306  {
1307  if (remove_vport_table_entry(&m_vportTable, ntohl(ovpm->vport)))
1308  {
1309  SendErrorMsg(OFPET_BAD_ACTION,
1310  OFPET_VPORT_MOD_FAILED,
1311  ovpm,
1312  ntohs(ovpm->header.length));
1313  }
1314  }
1315 
1316  return 0;
1317 }
1318 
1319 int
1320 OpenFlowSwitchNetDevice::AddFlow(const ofp_flow_mod* ofm)
1321 {
1322  size_t actions_len = ntohs(ofm->header.length) - sizeof *ofm;
1323 
1324  // Allocate memory.
1325  sw_flow* flow = flow_alloc(actions_len);
1326  if (!flow)
1327  {
1328  if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1329  {
1330  discard_buffer(ntohl(ofm->buffer_id));
1331  }
1332  return -ENOMEM;
1333  }
1334 
1335  flow_extract_match(&flow->key, &ofm->match);
1336 
1337  uint16_t v_code = ofi::ValidateActions(&flow->key, ofm->actions, actions_len);
1338  if (v_code != ACT_VALIDATION_OK)
1339  {
1340  SendErrorMsg(OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
1341  flow_free(flow);
1342  if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1343  {
1344  discard_buffer(ntohl(ofm->buffer_id));
1345  }
1346  return -ENOMEM;
1347  }
1348 
1349  // Fill out flow.
1350  flow->priority = flow->key.wildcards ? ntohs(ofm->priority) : -1;
1351  flow->idle_timeout = ntohs(ofm->idle_timeout);
1352  flow->hard_timeout = ntohs(ofm->hard_timeout);
1353  flow->used = flow->created = time_now();
1354  flow->sf_acts->actions_len = actions_len;
1355  flow->byte_count = 0;
1356  flow->packet_count = 0;
1357  memcpy(flow->sf_acts->actions, ofm->actions, actions_len);
1358 
1359  // Act.
1360  int error = chain_insert(m_chain, flow);
1361  if (error)
1362  {
1363  if (error == -ENOBUFS)
1364  {
1365  SendErrorMsg(OFPET_FLOW_MOD_FAILED,
1366  OFPFMFC_ALL_TABLES_FULL,
1367  ofm,
1368  ntohs(ofm->header.length));
1369  }
1370  flow_free(flow);
1371  if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1372  {
1373  discard_buffer(ntohl(ofm->buffer_id));
1374  }
1375  return error;
1376  }
1377 
1378  NS_LOG_INFO("Added new flow.");
1379  if (ntohl(ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
1380  {
1381  ofpbuf* buffer = retrieve_buffer(ofm->buffer_id); // ntohl(ofm->buffer_id)
1382  if (buffer)
1383  {
1384  sw_flow_key key;
1385  flow_used(flow, buffer);
1386  flow_extract(buffer,
1387  ntohs(ofm->match.in_port),
1388  &key.flow); // ntohs(ofm->match.in_port);
1389  ofi::ExecuteActions(this,
1390  ofm->buffer_id,
1391  buffer,
1392  &key,
1393  ofm->actions,
1394  actions_len,
1395  false);
1396  ofpbuf_delete(buffer);
1397  }
1398  else
1399  {
1400  return -ESRCH;
1401  }
1402  }
1403  return 0;
1404 }
1405 
1406 int
1407 OpenFlowSwitchNetDevice::ModFlow(const ofp_flow_mod* ofm)
1408 {
1409  sw_flow_key key;
1410  flow_extract_match(&key, &ofm->match);
1411 
1412  size_t actions_len = ntohs(ofm->header.length) - sizeof *ofm;
1413 
1414  uint16_t v_code = ofi::ValidateActions(&key, ofm->actions, actions_len);
1415  if (v_code != ACT_VALIDATION_OK)
1416  {
1417  SendErrorMsg((ofp_error_type)OFPET_BAD_ACTION, v_code, ofm, ntohs(ofm->header.length));
1418  if (ntohl(ofm->buffer_id) != (uint32_t)-1)
1419  {
1420  discard_buffer(ntohl(ofm->buffer_id));
1421  }
1422  return -ENOMEM;
1423  }
1424 
1425  uint16_t priority = key.wildcards ? ntohs(ofm->priority) : -1;
1426  int strict = (ofm->command == htons(OFPFC_MODIFY_STRICT)) ? 1 : 0;
1427  chain_modify(m_chain, &key, priority, strict, ofm->actions, actions_len);
1428 
1429  if (ntohl(ofm->buffer_id) != std::numeric_limits<uint32_t>::max())
1430  {
1431  ofpbuf* buffer = retrieve_buffer(ofm->buffer_id); // ntohl (ofm->buffer_id)
1432  if (buffer)
1433  {
1434  sw_flow_key skb_key;
1435  flow_extract(buffer,
1436  ntohs(ofm->match.in_port),
1437  &skb_key.flow); // ntohs(ofm->match.in_port);
1438  ofi::ExecuteActions(this,
1439  ofm->buffer_id,
1440  buffer,
1441  &skb_key,
1442  ofm->actions,
1443  actions_len,
1444  false);
1445  ofpbuf_delete(buffer);
1446  }
1447  else
1448  {
1449  return -ESRCH;
1450  }
1451  }
1452  return 0;
1453 }
1454 
1455 int
1456 OpenFlowSwitchNetDevice::ReceiveFlow(const void* msg)
1457 {
1459  const ofp_flow_mod* ofm = (ofp_flow_mod*)msg;
1460  uint16_t command = ntohs(ofm->command);
1461 
1462  if (command == OFPFC_ADD)
1463  {
1464  return AddFlow(ofm);
1465  }
1466  else if ((command == OFPFC_MODIFY) || (command == OFPFC_MODIFY_STRICT))
1467  {
1468  return ModFlow(ofm);
1469  }
1470  else if (command == OFPFC_DELETE)
1471  {
1472  sw_flow_key key;
1473  flow_extract_match(&key, &ofm->match);
1474  return chain_delete(m_chain, &key, ofm->out_port, 0, 0) ? 0 : -ESRCH;
1475  }
1476  else if (command == OFPFC_DELETE_STRICT)
1477  {
1478  sw_flow_key key;
1479  uint16_t priority;
1480  flow_extract_match(&key, &ofm->match);
1481  priority = key.wildcards ? ntohs(ofm->priority) : -1;
1482  return chain_delete(m_chain, &key, ofm->out_port, priority, 1) ? 0 : -ESRCH;
1483  }
1484  else
1485  {
1486  return -ENODEV;
1487  }
1488 }
1489 
1490 int
1491 OpenFlowSwitchNetDevice::StatsDump(ofi::StatsDumpCallback* cb)
1492 {
1493  ofp_stats_reply* osr;
1494  ofpbuf* buffer;
1495  int err;
1496 
1497  if (cb->done)
1498  {
1499  return 0;
1500  }
1501 
1502  osr = (ofp_stats_reply*)MakeOpenflowReply(sizeof *osr, OFPT_STATS_REPLY, &buffer);
1503  osr->type = htons(cb->s->type);
1504  osr->flags = 0;
1505 
1506  err = cb->s->DoDump(this, cb->state, buffer);
1507  if (err >= 0)
1508  {
1509  if (err == 0)
1510  {
1511  cb->done = true;
1512  }
1513  else
1514  {
1515  // Buffer might have been reallocated, so find our data again.
1516  osr = (ofp_stats_reply*)ofpbuf_at_assert(buffer, 0, sizeof *osr);
1517  osr->flags = ntohs(OFPSF_REPLY_MORE);
1518  }
1519 
1520  int err2 = SendOpenflowBuffer(buffer);
1521  if (err2)
1522  {
1523  err = err2;
1524  }
1525  }
1526 
1527  return err;
1528 }
1529 
1530 void
1531 OpenFlowSwitchNetDevice::StatsDone(ofi::StatsDumpCallback* cb)
1532 {
1533  if (cb)
1534  {
1535  cb->s->DoCleanup(cb->state);
1536  free(cb->s);
1537  free(cb);
1538  }
1539 }
1540 
1541 int
1542 OpenFlowSwitchNetDevice::ReceiveStatsRequest(const void* oh)
1543 {
1544  const ofp_stats_request* rq = (ofp_stats_request*)oh;
1545  size_t rq_len = ntohs(rq->header.length);
1546  int type = ntohs(rq->type);
1547  int body_len = rq_len - offsetof(ofp_stats_request, body);
1548  ofi::Stats* st = new ofi::Stats((ofp_stats_types)type, (unsigned)body_len);
1549 
1550  if (!st)
1551  {
1552  return -EINVAL;
1553  }
1554 
1555  ofi::StatsDumpCallback cb;
1556  cb.done = false;
1557  cb.rq = (ofp_stats_request*)xmemdup(rq, rq_len);
1558  cb.s = st;
1559  cb.state = nullptr;
1560  cb.swtch = this;
1561 
1562  if (cb.s)
1563  {
1564  int err = cb.s->DoInit(rq->body, body_len, &cb.state);
1565  if (err)
1566  {
1567  NS_LOG_WARN("failed initialization of stats request type " << type << ": "
1568  << strerror(-err));
1569  free(cb.rq);
1570  return err;
1571  }
1572  }
1573 
1574  if (m_controller)
1575  {
1576  m_controller->StartDump(&cb);
1577  }
1578  else
1579  {
1580  NS_LOG_ERROR(
1581  "Switch needs to be registered to a controller in order to start the stats reply.");
1582  }
1583 
1584  return 0;
1585 }
1586 
1587 int
1588 OpenFlowSwitchNetDevice::ReceiveEchoRequest(const void* oh)
1589 {
1590  return SendOpenflowBuffer(make_echo_reply((ofp_header*)oh));
1591 }
1592 
1593 int
1594 OpenFlowSwitchNetDevice::ReceiveEchoReply(const void* oh)
1595 {
1596  return 0;
1597 }
1598 
1599 int
1600 OpenFlowSwitchNetDevice::ForwardControlInput(const void* msg, size_t length)
1601 {
1602  // Check encapsulated length.
1603  ofp_header* oh = (ofp_header*)msg;
1604  if (ntohs(oh->length) > length)
1605  {
1606  return -EINVAL;
1607  }
1608  assert(oh->version == OFP_VERSION);
1609 
1610  int error = 0;
1611 
1612  // Figure out how to handle it.
1613  switch (oh->type)
1614  {
1615  case OFPT_FEATURES_REQUEST:
1616  error = length < sizeof(ofp_header) ? -EFAULT : ReceiveFeaturesRequest(msg);
1617  break;
1618  case OFPT_GET_CONFIG_REQUEST:
1619  error = length < sizeof(ofp_header) ? -EFAULT : ReceiveGetConfigRequest(msg);
1620  break;
1621  case OFPT_SET_CONFIG:
1622  error = length < sizeof(ofp_switch_config) ? -EFAULT : ReceiveSetConfig(msg);
1623  break;
1624  case OFPT_PACKET_OUT:
1625  error = length < sizeof(ofp_packet_out) ? -EFAULT : ReceivePacketOut(msg);
1626  break;
1627  case OFPT_FLOW_MOD:
1628  error = length < sizeof(ofp_flow_mod) ? -EFAULT : ReceiveFlow(msg);
1629  break;
1630  case OFPT_PORT_MOD:
1631  error = length < sizeof(ofp_port_mod) ? -EFAULT : ReceivePortMod(msg);
1632  break;
1633  case OFPT_STATS_REQUEST:
1634  error = length < sizeof(ofp_stats_request) ? -EFAULT : ReceiveStatsRequest(msg);
1635  break;
1636  case OFPT_ECHO_REQUEST:
1637  error = length < sizeof(ofp_header) ? -EFAULT : ReceiveEchoRequest(msg);
1638  break;
1639  case OFPT_ECHO_REPLY:
1640  error = length < sizeof(ofp_header) ? -EFAULT : ReceiveEchoReply(msg);
1641  break;
1642  case OFPT_VPORT_MOD:
1643  error = length < sizeof(ofp_vport_mod) ? -EFAULT : ReceiveVPortMod(msg);
1644  break;
1645  case OFPT_VPORT_TABLE_FEATURES_REQUEST:
1646  error = length < sizeof(ofp_header) ? -EFAULT : ReceiveVPortTableFeaturesRequest(msg);
1647  break;
1648  default:
1649  SendErrorMsg((ofp_error_type)OFPET_BAD_REQUEST,
1650  (ofp_bad_request_code)OFPBRC_BAD_TYPE,
1651  msg,
1652  length);
1653  error = -EINVAL;
1654  }
1655 
1656  if (msg)
1657  {
1658  free((ofpbuf*)msg);
1659  }
1660  return error;
1661 }
1662 
1663 sw_chain*
1664 OpenFlowSwitchNetDevice::GetChain()
1665 {
1666  return m_chain;
1667 }
1668 
1669 uint32_t
1670 OpenFlowSwitchNetDevice::GetNSwitchPorts() const
1671 {
1673  return m_ports.size();
1674 }
1675 
1676 ofi::Port
1677 OpenFlowSwitchNetDevice::GetSwitchPort(uint32_t n) const
1678 {
1680  return m_ports[n];
1681 }
1682 
1683 int
1684 OpenFlowSwitchNetDevice::GetSwitchPortIndex(ofi::Port p)
1685 {
1686  for (size_t i = 0; i < m_ports.size(); i++)
1687  {
1688  if (m_ports[i].netdev == p.netdev)
1689  {
1690  return i;
1691  }
1692  }
1693  return -1;
1694 }
1695 
1696 vport_table_t
1697 OpenFlowSwitchNetDevice::GetVPortTable()
1698 {
1699  return m_vportTable;
1700 }
1701 
1702 } // namespace ns3
1703 
1704 #endif // NS3_OPENFLOW
double f(double x, void *params)
Definition: 80211b.c:71
#define max(a, b)
Definition: 80211b.c:43
uint64_t m_id
Unique identifier for this switch, needed for OpenFlow.
static const char * GetSerialNumber()
static const char * GetSoftwareDescription()
uint16_t m_flags
Flags; configurable by the controller.
static const char * GetManufacturerDescription()
uint16_t m_missSendLen
Flow Table Miss Send Length; configurable by the controller.
static TypeId GetTypeId()
Register this type.
static const char * GetHardwareDescription()
Time m_lookupDelay
Flow Table Lookup Delay [overhead].
TypeId AddConstructor()
Record in this TypeId the fact that the default constructor is accessible.
Definition: type-id.h:653
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
uint16_t port
Definition: dsdv-manet.cc:45
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
Definition: fd-emu-send.cc:54
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:46
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
struct ofpbuf * BufferFromPacket(Ptr< const Packet > packet, size_t bodyRoom, size_t headRoom)
Create an internal BOFUSS buffer from ns3::Packet.
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
address
Definition: first.py:40
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:848
bool IsMulticast(const Address &ad)
Address family-independent test for a multicast address.
void ExecuteVPortActions(Ptr< OpenFlowSwitchNetDevice > swtch, uint64_t packet_uid, ofpbuf *buffer, sw_flow_key *key, const ofp_action_header *actions, size_t actions_len)
Executes a list of virtual port table entry actions.
void ExecuteActions(Ptr< OpenFlowSwitchNetDevice > swtch, uint64_t packet_uid, ofpbuf *buffer, sw_flow_key *key, const ofp_action_header *actions, size_t actions_len, int ignore_no_fwd)
Executes a list of flow table actions.
uint16_t ValidateActions(const sw_flow_key *key, const ofp_action_header *actions, size_t actions_len)
Validates a list of flow table actions.
uint16_t ValidateVPortActions(const ofp_action_header *actions, size_t actions_len)
Validates a list of virtual port table entry actions.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
time_t time_now(void)
Overriding BOFUSS time_now weak function from timeval.c.
void discard_buffer(uint32_t id)
ofpbuf * retrieve_buffer(uint32_t id)
#define OFP_SUPPORTED_CAPABILITIES
uint32_t save_buffer(ofpbuf *)
#define N_PKT_BUFFERS
#define OFP_SUPPORTED_VPORT_TABLE_ACTIONS
#define OFP_SUPPORTED_ACTIONS
uint8_t data[writeSize]