Exemple #1
0
static void
port_status( uint64_t datapath_id, uint32_t transaction_id, uint8_t reason,
             struct ofp_phy_port phy_port, void *user_data ) {
  UNUSED( transaction_id );
  UNUSED( user_data );

  sw_entry *sw = lookup_sw_entry( &datapath_id );
  if ( sw == NULL ) {
    warn( "Received port-status, but switch(%#" PRIx64 ") is not found.", datapath_id );
    return;
  }
  port_entry *port = lookup_port_entry( sw, phy_port.port_no, phy_port.name );
  switch ( reason ) {
    case OFPPR_ADD:
      if ( port != NULL ) {
        warn( "Failed to add port(%u, `%s'), switch(%#" PRIx64 ").",
              phy_port.port_no, phy_port.name, datapath_id );
        return;
      }
      add_notification( sw, &phy_port );
      break;

    case OFPPR_DELETE:
      if ( port == NULL ) {
        warn( "Failed to delete port(%u, `%s'), switch(%#" PRIx64 ").",
              phy_port.port_no, phy_port.name, datapath_id );
        return;
      }
      delete_notification( sw, port );
      break;

    case OFPPR_MODIFY:
      if ( port == NULL ) {
        warn( "Failed to modify port(%u, `%s'), switch(%#" PRIx64 ").",
              phy_port.port_no, phy_port.name, datapath_id );
        return;
      }
      if ( port->port_no != phy_port.port_no ) {
        delete_notification( sw, port );
        add_notification( sw, &phy_port );
      } else {
        update_notification( sw, port, &phy_port );
      }
      break;
    default:
      warn( "Failed to handle port status: unknown reason(%u) from switch(%#" PRIx64 ").",
            reason, datapath_id );
      return;
  }
}
/*!	Notifies all interested listeners of this transaction about the \a event.
	If \a event is a closing event (ie. TRANSACTION_ENDED, and
	TRANSACTION_ABORTED), all listeners except those listening to
	TRANSACTION_WRITTEN will be removed.
*/
static void
notify_transaction_listeners(block_cache* cache, cache_transaction* transaction,
	int32_t event)
{
	bool isClosing = is_closing_event(event);
	bool isWritten = is_written_event(event);

	ListenerList::Iterator iterator = transaction->listeners.GetIterator();
	while (iterator.HasNext()) {
		cache_listener* listener = iterator.Next();

		bool remove = (isClosing && !is_written_event(listener->events))
			|| (isWritten && is_written_event(listener->events));
		if (remove)
			iterator.Remove();

		if ((listener->events & event) != 0)
			add_notification(cache, listener, event, remove);
		else if (remove)
			delete_notification(listener);
	}

	// This must work asynchronously in the kernel, but since we're not using
	// most transaction events, we can do it here.
	flush_pending_notifications(cache);
}
Exemple #3
0
int delete_message(message* p)
{
	if(p==NULL) return 0;
	delete_command(p->commands);
	delete_notification(p->notifications);
	delete_request(p->requests);
	free(p);
	return 1;
}
Exemple #4
0
int delete_notification(notification* p)
{
	if(p==NULL) return 0;
	delete_notification(p->next);
	delete_data_msg(p->data_message);
	delete_fault_msg(p->fault_message);
	free(p->interface_name);
	free(p->interface_id);
	free(p);
	return 1;
}
/*!	Removes and deletes all listeners that are still monitoring this
	transaction.
*/
static void
remove_transaction_listeners(block_cache* cache, cache_transaction* transaction)
{
	ListenerList::Iterator iterator = transaction->listeners.GetIterator();
	while (iterator.HasNext()) {
		cache_listener* listener = iterator.Next();
		iterator.Remove();

		delete_notification(listener);
	}
}
Exemple #6
0
int delete_interface(interface* p)
{
	if(p==NULL) return 0;
	delete_interface(p->next);
	delete_qualifier(p->qualifiers);
	delete_variable(p->variables);
	delete_command(p->commands);
	delete_notification(p->notifications);
	delete_request(p->requests);
	free(p->name);
	free(p->extends);
	free(p->id);
	free(p->description);
	free(p);
	return 1;
}
Exemple #7
0
static void
switch_disconnected( uint64_t datapath_id, void *user_data ) {
  UNUSED( user_data );

  sw_entry *sw = lookup_sw_entry( &datapath_id );
  if ( sw == NULL ) {
    warn( "Received switch-disconnected event, but switch(%#" PRIx64 ") is not found.", datapath_id );
    return;
  }
  const list_element *list, *next;
  for ( list = sw->port_table; list != NULL; list = next ) {
    next = list->next;
    delete_notification( sw, list->data );
  }
  delete_sw_entry( sw );
  debug( "Switch(%#" PRIx64 ") is disconnected.", datapath_id );
}
Exemple #8
0
static void
switch_features_reply( uint64_t datapath_id, uint32_t transaction_id,
                       uint32_t n_buffers, uint8_t n_tables,
                       uint32_t capabilities, uint32_t actions,
                       const list_element *phy_ports, void *user_data ) {

  UNUSED( n_buffers );
  UNUSED( n_tables );
  UNUSED( capabilities );
  UNUSED( actions );
  UNUSED( user_data );

  sw_entry *sw = lookup_sw_entry( &datapath_id );
  if ( sw == NULL ) {
    warn( "Received features-reply from switch(%#" PRIx64 "), but the switch is not found.", datapath_id );
    return;
  }
  debug( "Received features-reply from switch(%#" PRIx64 ").", datapath_id );
  sw->id = transaction_id;

  const list_element *list, *next;
  for ( list = phy_ports; list != NULL; list = list->next ) {
    const struct ofp_phy_port *phy_port = list->data;
    if ( phy_port->port_no > OFPP_MAX && phy_port->port_no != OFPP_LOCAL ) {
      warn( "Ignore phy_port(port:%u) in features-reply from switch(%#" PRIx64 ").",
            phy_port->port_no, datapath_id );
      continue;
    }
    port_entry *port = update_port_entry( sw, phy_port->port_no, phy_port->name );
    port->id = transaction_id;
    update_notification( sw, port, phy_port );
    debug( "Updated features-reply from switch(%#" PRIx64 "), port_no(%u).",
           datapath_id, phy_port->port_no );
  }
  for ( list = sw->port_table; list != NULL; list = next ) {
    next = list->next;
    port_entry *port = list->data;
    if ( port->id == transaction_id ) {
      continue;
    }
    delete_notification( sw, port );
    debug( "Deleted port(%u) in switch(%#" PRIx64 ")", port->port_no, datapath_id );
  }
}
/*!	Adds the notification to the pending notifications list, or, if it's
	already part of it, updates its events_pending field.
	Also marks the notification to be deleted if \a deleteNotification
	is \c true.
	Triggers the notifier thread to run.
*/
static void
add_notification(block_cache* cache, cache_notification* notification,
	int32_t event, bool deleteNotification)
{
	if (notification->hook == NULL)
		return;

	int32_t pending = fssh_atomic_or(&notification->events_pending, event);
	if (pending == 0) {
		// not yet part of the notification list
		MutexLocker locker(sNotificationsLock);
		if (deleteNotification)
			notification->delete_after_event = true;
		cache->pending_notifications.Add(notification);
	} else if (deleteNotification) {
		// we might need to delete it ourselves if we're late
		delete_notification(notification);
	}
}