Beispiel #1
0
  def _print_buffers(self):
    # TODO(cs): this method should also be added to Interactive.
    # Note that there shouldn't be any pending state changes in record mode,
    # only pending message sends/receives.
    buffered_events = []
    log.info("Pending Receives:")
    of_buf = self.simulation.openflow_buffer
    for (dpid, controller_id) in of_buf.conns_with_pending_receives():
      for p in of_buf.get_pending_receives(dpid, controller_id):
        log.info("- %r", p)
        message = of_buf.get_message_receipt(p)
        b64_packet = base64_encode(message)
        event = ControlMessageReceive(p.dpid, p.controller_id, p.fingerprint, b64_packet=b64_packet)
        buffered_events.append(event)

    log.info("Pending Sends:")
    for (dpid, controller_id) in of_buf.conns_with_pending_sends():
      for p in of_buf.get_pending_sends(dpid, controller_id):
        log.info("- %r", p)
        message = of_buf.get_message_send(p)
        b64_packet = base64_encode(message)
        event = ControlMessageSend(p.dpid, p.controller_id, p.fingerprint, b64_packet=b64_packet)
        buffered_events.append(event)

    if self._input_logger is not None:
      self._input_logger.dump_buffered_events(buffered_events)
Beispiel #2
0
  def check_pending_messages(self, pass_through=False):
    of_buf = self.simulation.openflow_buffer
    for (dpid, controller_id) in of_buf.conns_with_pending_receives():
      for pending_receipt in of_buf.get_pending_receives(dpid, controller_id):
        if (not pass_through and
            self.random.random() > self.params.ofp_message_receipt_rate):
          break
        message = of_buf.get_message_receipt(pending_receipt)
        b64_packet = base64_encode(message)
        self._log_input_event(ControlMessageReceive(pending_receipt.dpid,
                                                    pending_receipt.controller_id,
                                                    pending_receipt.fingerprint,
                                                    b64_packet=b64_packet))
        of_buf.schedule(pending_receipt)

    for (dpid, controller_id) in of_buf.conns_with_pending_sends():
      for pending_send in of_buf.get_pending_sends(dpid, controller_id):
        if (not pass_through and
            self.random.random() > self.params.ofp_message_send_rate):
          break
        message = of_buf.get_message_send(pending_send)
        b64_packet = base64_encode(message)
        self._log_input_event(ControlMessageSend(pending_send.dpid,
                                                 pending_send.controller_id,
                                                 pending_send.fingerprint,
                                                 b64_packet=b64_packet))
        of_buf.schedule(pending_send)
Beispiel #3
0
 def check_pending_messages(self, pass_through=False):
     for pending_receipt in self.simulation.openflow_buffer.pending_receives(
     ):
         # TODO(cs): this is a really dumb way to fuzz packet receipt scheduling
         if (self.random.random() < self.params.ofp_message_receipt_rate
                 or pass_through):
             message = self.simulation.openflow_buffer.schedule(
                 pending_receipt)
             b64_packet = base64_encode(message)
             self._log_input_event(
                 ControlMessageReceive(pending_receipt.dpid,
                                       pending_receipt.controller_id,
                                       pending_receipt.fingerprint,
                                       b64_packet=b64_packet))
     for pending_send in self.simulation.openflow_buffer.pending_sends():
         if (self.random.random() < self.params.ofp_message_send_rate
                 or pass_through):
             message = self.simulation.openflow_buffer.schedule(
                 pending_send)
             b64_packet = base64_encode(message)
             self._log_input_event(
                 ControlMessageSend(pending_send.dpid,
                                    pending_send.controller_id,
                                    pending_send.fingerprint,
                                    b64_packet=b64_packet))
Beispiel #4
0
    def check_pending_messages(self, pass_through=False):
        of_buf = self.simulation.openflow_buffer
        for (dpid, controller_id) in of_buf.conns_with_pending_receives():
            for pending_receipt in of_buf.get_pending_receives(
                    dpid, controller_id):
                if (not pass_through and self.random.random() >
                        self.params.ofp_message_receipt_rate):
                    break
                message = of_buf.get_message_receipt(pending_receipt)
                b64_packet = base64_encode(message)
                self._log_input_event(
                    ControlMessageReceive(pending_receipt.dpid,
                                          pending_receipt.controller_id,
                                          pending_receipt.fingerprint,
                                          b64_packet=b64_packet))
                of_buf.schedule(pending_receipt)

        for (dpid, controller_id) in of_buf.conns_with_pending_sends():
            for pending_send in of_buf.get_pending_sends(dpid, controller_id):
                if (not pass_through and self.random.random() >
                        self.params.ofp_message_send_rate):
                    break
                message = of_buf.get_message_send(pending_send)
                b64_packet = base64_encode(message)
                self._log_input_event(
                    ControlMessageSend(pending_send.dpid,
                                       pending_send.controller_id,
                                       pending_send.fingerprint,
                                       b64_packet=b64_packet))
                of_buf.schedule(pending_send)
Beispiel #5
0
    def _print_buffers(self):
        # TODO(cs): this method should also be added to Interactive.
        # Note that there shouldn't be any pending state changes in record mode,
        # only pending message sends/receives.
        buffered_events = []
        log.info("Pending Receives:")
        of_buf = self.simulation.openflow_buffer
        for (dpid, controller_id) in of_buf.conns_with_pending_receives():
            for p in of_buf.get_pending_receives(dpid, controller_id):
                log.info("- %r", p)
                message = of_buf.get_message_receipt(p)
                b64_packet = base64_encode(message)
                event = ControlMessageReceive(p.dpid,
                                              p.controller_id,
                                              p.fingerprint,
                                              b64_packet=b64_packet)
                buffered_events.append(event)

        log.info("Pending Sends:")
        for (dpid, controller_id) in of_buf.conns_with_pending_sends():
            for p in of_buf.get_pending_sends(dpid, controller_id):
                log.info("- %r", p)
                message = of_buf.get_message_send(p)
                b64_packet = base64_encode(message)
                event = ControlMessageSend(p.dpid,
                                           p.controller_id,
                                           p.fingerprint,
                                           b64_packet=b64_packet)
                buffered_events.append(event)

        if self._input_logger is not None:
            self._input_logger.dump_buffered_events(buffered_events)
Beispiel #6
0
  def check_pending_commands(self):
    ''' If Fuzzer is configured to delay flow mods, this decides whether
    each switch is allowed to process a buffered flow mod '''

    def should_fail_flow_mod(command):
      # super simple filter to tell whether to apply or actively fail a flow_mod
      return self.random.random() < self.params.ofp_flow_mod_failure_rate

    if self.delay_flow_mods:
      for switch in self.simulation.topology.switches:
        assert(isinstance(switch, FuzzSoftwareSwitch))
        # first decide if we should try to process the next command from the switch
        if switch.has_pending_commands() and (self.random.random() < self.params.ofp_cmd_passthrough_rate):
          (cmd, pending_receipt) = switch.get_next_command()
          # then check whether we should make the attempt to process the next command fail
          if should_fail_flow_mod(cmd):
            eventclass = FailFlowMod
          else:
            eventclass = ProcessFlowMod
            switch.process_delayed_command(pending_receipt)
          b64_packet = base64_encode(cmd)
          self._log_input_event(eventclass(pending_receipt.dpid,
                                           pending_receipt.controller_id,
                                           pending_receipt.fingerprint,
                                           b64_packet=b64_packet))
Beispiel #7
0
    def check_pending_commands(self):
        ''' If Fuzzer is configured to delay flow mods, this decides whether 
    each switch is allowed to process a buffered flow mod '''
        def should_fail_flow_mod(command):
            # super simple filter to tell whether to apply or actively fail a flow_mod
            return self.random.random() < self.params.ofp_flow_mod_failure_rate

        if self.delay_flow_mods:
            for switch in self.simulation.topology.switches:
                assert (isinstance(switch, FuzzSoftwareSwitch))
                # first decide if we should try to process the next command from the switch
                if (self.random.random() < self.params.ofp_cmd_passthrough_rate
                    ) and switch.has_pending_commands():
                    (cmd, pending_receipt) = switch.get_next_command()
                    # then check whether we should make the attempt to process the next command fail
                    if should_fail_flow_mod(cmd):
                        eventclass = FailFlowMod
                    else:
                        eventclass = ProcessFlowMod
                    switch.process_delayed_command(pending_receipt)
                    b64_packet = base64_encode(cmd)
                    self._log_input_event(
                        eventclass(pending_receipt.dpid,
                                   pending_receipt.controller_id,
                                   pending_receipt.fingerprint,
                                   b64_packet=b64_packet))
Beispiel #8
0
    def _check_unexpected_cp_messages(self, dag, current_index):
        ''' If throughout replay we observe new messages that weren't in the
    original trace, we (usually) want to let them through. This is especially true
    for messages that are related to timers, such as LLDP, since timings will
    often change during replay, and we don't want to unnecessarily change the
    controller's behavior. '''
        if not self.allow_unexpected_messages:
            return
        # TODO(cs): evaluate whether _check_unexpected_cp_messages is more or less
        # effective than whitelisting cp message types (in OpenflowBuffer).
        # Compare executions with visualization tool.
        # Currently it appears that this method is too liberal, and ends up
        # causing timouts as a result of letting messages through.

        # First, build a set of expected ControlMessageSends/Receives fingerprints
        # within the next expected_message_round_window rounds.
        start_round = dag.events[current_index].round
        expected_receive_fingerprints = set()
        expected_send_fingerprints = set()
        for i in xrange(current_index, len(dag.events)):
            event = dag.events[i]
            if event.round - start_round > self.expected_message_round_window:
                break
            if type(event) == ControlMessageReceive:
                (_, of_fingerprint, dpid, cid) = event.fingerprint
                expected_receive_fingerprints.add((of_fingerprint, dpid, cid))
            if type(event) == ControlMessageSend:
                (_, of_fingerprint, dpid, cid) = event.fingerprint
                expected_send_fingerprints.add((of_fingerprint, dpid, cid))

        # Now check pending messages.
        for expected_fingerprints, messages in [
            (expected_receive_fingerprints,
             self.simulation.openflow_buffer.pending_receives),
            (expected_send_fingerprints,
             self.simulation.openflow_buffer.pending_sends)
        ]:
            for pending_message in messages:
                fingerprint = (pending_message.fingerprint,
                               pending_message.dpid,
                               pending_message.controller_id)
                if fingerprint not in expected_fingerprints:
                    message = self.simulation.openflow_buffer.schedule(
                        pending_message)
                    log.debug("Allowed unexpected message %s" % message)
                    b64_packet = base64_encode(message)
                    # Monkeypatch a "new internal event" marker to be logged to the JSON trace
                    # (All fields picked up by event.to_json())
                    event_type = ControlMessageReceive if type(
                        pending_message
                    ) == PendingReceive else ControlMessageSend
                    log_event = event_type(pending_message.dpid,
                                           pending_message.controller_id,
                                           pending_message.fingerprint,
                                           b64_packet=b64_packet)
                    log_event.new_internal_event = True
                    log_event.replay_time = SyncTime.now()
                    self.passed_unexpected_messages.append(repr(log_event))
                    self._log_input_event(log_event)
Beispiel #9
0
 def check_pending_messages(self, pass_through=False):
   for pending_receipt in self.simulation.openflow_buffer.pending_receives():
     # TODO(cs): this is a really dumb way to fuzz packet receipt scheduling
     if (self.random.random() < self.params.ofp_message_receipt_rate or
         pass_through):
       message = self.simulation.openflow_buffer.schedule(pending_receipt)
       b64_packet = base64_encode(message)
       self._log_input_event(ControlMessageReceive(pending_receipt.dpid,
                                                   pending_receipt.controller_id,
                                                   pending_receipt.fingerprint,
                                                   b64_packet=b64_packet))
   for pending_send in self.simulation.openflow_buffer.pending_sends():
     if (self.random.random() < self.params.ofp_message_send_rate or
         pass_through):
       message = self.simulation.openflow_buffer.schedule(pending_send)
       b64_packet = base64_encode(message)
       self._log_input_event(ControlMessageSend(pending_send.dpid,
                                                pending_send.controller_id,
                                                pending_send.fingerprint,
                                                b64_packet=b64_packet))
Beispiel #10
0
 def insert_pending_send(self, dpid, controller_id, ofp_message, conn):
   ''' Called by DeferredOFConnection to insert messages into our buffer '''
   fingerprint = OFFingerprint.from_pkt(ofp_message)
   if self.pass_through_whitelisted_packets and self.in_whitelist(fingerprint):
     conn.allow_message_send(ofp_message)
     return
   conn_message = (conn, ofp_message)
   pending_send = PendingSend(dpid, controller_id, fingerprint)
   self.pendingsend2conn_messages[pending_send].append(conn_message)
   b64_packet = base64_encode(ofp_message)
   self.raiseEventNoErrors(PendingMessage(pending_send, b64_packet, send_event=True))
   return pending_send
Beispiel #11
0
 def insert_pending_receipt(self, dpid, controller_id, ofp_message, conn):
   ''' Called by DeferredOFConnection to insert messages into our buffer '''
   fingerprint = OFFingerprint.from_pkt(ofp_message)
   if self.pass_through_whitelisted_packets and self.in_whitelist(fingerprint):
     conn.allow_message_receipt(ofp_message)
     return
   conn_message = (conn, ofp_message)
   message_id = PendingReceive(dpid, controller_id, fingerprint)
   self.pending_receives.insert(message_id, conn_message)
   b64_packet = base64_encode(ofp_message)
   self.raiseEventNoErrors(PendingMessage(message_id, b64_packet))
   return message_id
Beispiel #12
0
 def insert_pending_receipt(self, dpid, controller_id, ofp_message, conn):
     ''' Called by DeferredOFConnection to insert messages into our buffer '''
     fingerprint = OFFingerprint.from_pkt(ofp_message)
     if self.pass_through_whitelisted_packets and self.in_whitelist(
             fingerprint):
         conn.allow_message_receipt(ofp_message)
         return
     conn_message = (conn, ofp_message)
     message_id = PendingReceive(dpid, controller_id, fingerprint)
     self.pending_receives.insert(message_id, conn_message)
     b64_packet = base64_encode(ofp_message)
     self.raiseEventNoErrors(PendingMessage(message_id, b64_packet))
     return message_id
Beispiel #13
0
  def _check_unexpected_dp_messages(self, dag, current_index):
    ''' If throughout replay we observe new messages that weren't in the
    original trace, we (usually) want to let them through. This is especially true
    for messages that are related to timers, such as LLDP, since timings will
    often change during replay, and we don't want to unnecessarily change the
    controller's behavior. '''
    if not self.allow_unexpected_messages:
      return
    # TODO(cs): evaluate whether _check_unexpected_dp_messages is more or less
    # effective than _check_whitelisted_dp_messages. Compare executions with
    # visualization tool. Currently it appears that this method is too
    # liberal, and ends up causing timouts as a result of letting messages
    # through.

    # First, build a set of expected ControlMessageSends/Receives fingerprints
    # within the next expected_message_round_window rounds.
    start_round = dag.events[current_index].round
    expected_receive_fingerprints = set()
    expected_send_fingerprints = set()
    for i in xrange(current_index, len(dag.events)):
      event = dag.events[i]
      if event.round - start_round > self.expected_message_round_window:
        break
      if type(event) == ControlMessageReceive:
        (_, of_fingerprint, dpid, cid) = event.fingerprint
        expected_receive_fingerprints.add((of_fingerprint, dpid, cid))
      if type(event) == ControlMessageSend:
        (_, of_fingerprint, dpid, cid) = event.fingerprint
        expected_send_fingerprints.add((of_fingerprint, dpid, cid))

    # Now check pending messages.
    for expected_fingerprints, messages in [
         (expected_receive_fingerprints, self.simulation.openflow_buffer.pending_receives()),
         (expected_send_fingerprints, self.simulation.openflow_buffer.pending_sends())]:
      for pending_message in messages:
        fingerprint = (pending_message.fingerprint,
                       pending_message.dpid,
                       pending_message.controller_id)
        if fingerprint not in expected_fingerprints:
          message = self.simulation.openflow_buffer.schedule(pending_message)
          log.debug("Sending unexpected %s" % message)
          b64_packet = base64_encode(message)
          # Monkeypatch a "new internal event" marker to be logged to the JSON trace
          # (All fields picked up by event.to_json())
          event_type = ControlMessageReceive if type(pending_message) == PendingReceive else ControlMessageSend
          log_event = event_type(pending_message.dpid, pending_message.controller_id,
                                 pending_message.fingerprint, b64_packet=b64_packet)
          log_event.new_internal_event = True
          log_event.replay_time = SyncTime.now()
          self.passed_unexpected_messages.append(repr(log_event))
          self._log_input_event(log_event)
Beispiel #14
0
 def insert_pending_send(self, dpid, controller_id, ofp_message, conn):
     ''' Called by DeferredOFConnection to insert messages into our buffer '''
     fingerprint = OFFingerprint.from_pkt(ofp_message)
     if self.pass_through_whitelisted_packets and self.in_whitelist(
             fingerprint):
         conn.allow_message_send(ofp_message)
         return
     conn_message = (conn, ofp_message)
     pending_send = PendingSend(dpid, controller_id, fingerprint)
     self.pendingsend2conn_messages[pending_send].append(conn_message)
     b64_packet = base64_encode(ofp_message)
     self.raiseEventNoErrors(
         PendingMessage(pending_send, b64_packet, send_event=True))
     return pending_send
Beispiel #15
0
 def check_pending_commands(self):
   ''' If Fuzzer is configured to delay flow mods, this decides whether 
   each switch is allowed to process a buffered flow mod '''
   if self.delay_flow_mods:
     for switch in self.simulation.topology.switches:
       assert(isinstance(switch, FuzzSoftwareSwitch))
       if (self.random.random() < self.params.ofp_cmd_passthrough_rate):
         if switch.has_pending_commands():
           (message, pending_receipt) = switch.process_delayed_command()
           b64_packet = base64_encode(message)
           self._log_input_event(ProcessFlowMod(pending_receipt.dpid,
                                                pending_receipt.controller_id,
                                                pending_receipt.fingerprint,
                                                b64_packet=b64_packet))
Beispiel #16
0
 def insert_pending_send(self, dpid, controller_id, ofp_message, conn):
   ''' Called by DeferredOFConnection to insert messages into our buffer '''
   fingerprint = OFFingerprint.from_pkt(ofp_message)
   if (self.pass_through_sends or
       (self.pass_through_whitelisted_packets and self.in_whitelist(fingerprint))):
     conn.allow_message_send(ofp_message)
     return
   conn_message = (conn, ofp_message)
   message_id = PendingSend(dpid, controller_id, fingerprint)
   self.pending_sends.insert(message_id, conn_message)
   log.info("--- insert pending send: %s", message_id)
   b64_packet = base64_encode(ofp_message)
   self.raiseEventNoErrors(PendingMessage(message_id, b64_packet, send_event=True))
   return message_id
Beispiel #17
0
 def check_pending_commands(self):
   ''' If Fuzzer is configured to delay flow mods, this decides whether
   each switch is allowed to process a buffered flow mod '''
   if self.delay_flow_mods:
     for switch in self.simulation.topology.switches:
       assert(isinstance(switch, FuzzSoftwareSwitch))
       # first decide if we should try to process the next command from the switch
       if switch.has_pending_commands() and (self.random.random() < self.params.ofp_cmd_passthrough_rate):
         (cmd, pending_receipt) = switch.get_next_command()
         eventclass = ProcessFlowMod
         b64_packet = base64_encode(cmd)
         self._log_input_event(eventclass(pending_receipt.dpid,
                                          pending_receipt.controller_id,
                                          pending_receipt.fingerprint,
                                          b64_packet=b64_packet))
         switch.process_delayed_command(pending_receipt)
Beispiel #18
0
  def _print_buffers(self):
    # TODO(cs): this method should also be added to Interactive.
    # Note that there shouldn't be any pending state changes in record mode,
    # only pending message sends/receives.
    buffered_events = []
    log.info("Pending Messages:")
    for event_type, pending2conn_messages in [
            (ControlMessageReceive, self.simulation.openflow_buffer.pendingreceive2conn_messages),
            (ControlMessageSend, self.simulation.openflow_buffer.pendingsend2conn_messages)]:
      for p, conn_messages in pending2conn_messages.iteritems():
        log.info("- %r", p)
        for _, ofp_message in conn_messages:
          b64_packet = base64_encode(ofp_message)
          event = event_type(p.dpid, p.controller_id, p.fingerprint, b64_packet=b64_packet)
          buffered_events.append(event)

    if self._input_logger is not None:
      self._input_logger.dump_buffered_events(buffered_events)
Beispiel #19
0
 def check_pending_commands(self):
     ''' If Fuzzer is configured to delay flow mods, this decides whether
 each switch is allowed to process a buffered flow mod '''
     if self.delay_flow_mods:
         for switch in self.simulation.topology.switches:
             assert (isinstance(switch, FuzzSoftwareSwitch))
             # first decide if we should try to process the next command from the switch
             if switch.has_pending_commands() and (
                     self.random.random() <
                     self.params.ofp_cmd_passthrough_rate):
                 (cmd, pending_receipt) = switch.get_next_command()
                 eventclass = ProcessFlowMod
                 b64_packet = base64_encode(cmd)
                 self._log_input_event(
                     eventclass(pending_receipt.dpid,
                                pending_receipt.controller_id,
                                pending_receipt.fingerprint,
                                b64_packet=b64_packet))
                 switch.process_delayed_command(pending_receipt)
Beispiel #20
0
    def _print_buffers(self):
        # TODO(cs): this method should also be added to Interactive.
        # Note that there shouldn't be any pending state changes in record mode,
        # only pending message sends/receives.
        buffered_events = []
        log.info("Pending Messages:")
        for event_type, pending2conn_messages in [
            (ControlMessageReceive,
             self.simulation.openflow_buffer.pendingreceive2conn_messages),
            (ControlMessageSend,
             self.simulation.openflow_buffer.pendingsend2conn_messages)
        ]:
            for p, conn_messages in pending2conn_messages.iteritems():
                log.info("- %r", p)
                for _, ofp_message in conn_messages:
                    b64_packet = base64_encode(ofp_message)
                    event = event_type(p.dpid,
                                       p.controller_id,
                                       p.fingerprint,
                                       b64_packet=b64_packet)
                    buffered_events.append(event)

        if self._input_logger is not None:
            self._input_logger.dump_buffered_events(buffered_events)
Beispiel #21
0
 def _send_command(self, command):
     b64_pkt = base64_encode(command)
     self.json_worker.send(b64_pkt)
 def _send_command(self, command):
   b64_pkt = base64_encode(command)
   self.json_worker.send(b64_pkt)