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); }
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; }
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); } }
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; }
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 ); }
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(¬ification->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); } }