static void send_flow_removed_message(ft_entry_t *entry, indigo_fi_flow_removed_t reason) { of_flow_removed_t *msg; int rv = 0; uint32_t secs; uint32_t nsecs; indigo_time_t current; current = INDIGO_CURRENT_TIME; /* TODO get version from OFConnectionManager */ if ((msg = of_flow_removed_new(entry->match.version)) == NULL) { return; } calc_duration(current, entry->insert_time, &secs, &nsecs); of_flow_removed_xid_set(msg, ind_core_xid_alloc()); of_flow_removed_cookie_set(msg, entry->cookie); of_flow_removed_priority_set(msg, entry->priority); of_flow_removed_idle_timeout_set(msg, entry->idle_timeout); if (msg->version >= OF_VERSION_1_1) { of_flow_removed_table_id_set(msg, entry->table_id); } if (msg->version >= OF_VERSION_1_2) { of_flow_removed_hard_timeout_set(msg, entry->hard_timeout); } if (of_flow_removed_match_set(msg, &entry->match)) { LOG_ERROR("Failed to set match in flow removed message"); of_object_delete(msg); return; } if (reason > INDIGO_FLOW_REMOVED_DELETE) { /* Normalize entry */ reason = INDIGO_FLOW_REMOVED_DELETE; } of_flow_removed_reason_set(msg, reason); of_flow_removed_duration_sec_set(msg, secs); of_flow_removed_duration_nsec_set(msg, nsecs); of_flow_removed_packet_count_set(msg, entry->packets); of_flow_removed_byte_count_set(msg, entry->bytes); /* @fixme hard_timeout and table_id are not in OF 1.0 */ /* @fixme Should a cxn-id be specified? */ rv = indigo_cxn_send_controller_message(INDIGO_CXN_ID_UNSPECIFIED, msg); if (rv != INDIGO_ERROR_NONE) { LOG_ERROR("Error sending flow removed message"); return; } return; }
static int flow_removed_setup_from_flow_add_common(of_flow_removed_t *obj, of_flow_add_t *flow_add, int removed_match_offset, int add_match_offset) { int add_len, removed_len; of_wire_buffer_t *wbuf; int abs_offset; int delta; uint16_t val16; uint64_t cookie; of_octets_t match_octets; /* Transfer the match underlying object from add to removed obj */ wbuf = OF_OBJECT_TO_WBUF(obj); removed_len = _WIRE_MATCH_PADDED_LEN(obj, removed_match_offset); add_len = _WIRE_MATCH_PADDED_LEN(flow_add, add_match_offset); match_octets.bytes = add_len; match_octets.data = OF_OBJECT_BUFFER_INDEX(flow_add, add_match_offset); /* Copy data into flow removed */ abs_offset = OF_OBJECT_ABSOLUTE_OFFSET(obj, removed_match_offset); of_wire_buffer_replace_data(wbuf, abs_offset, removed_len, match_octets.data, add_len); /* Not scalar, update lengths if needed */ delta = add_len - removed_len; if (delta != 0) { /* Update parent(s) */ of_object_parent_length_update((of_object_t *)obj, delta); } of_flow_add_cookie_get(flow_add, &cookie); of_flow_removed_cookie_set(obj, cookie); of_flow_add_priority_get(flow_add, &val16); of_flow_removed_priority_set(obj, val16); of_flow_add_idle_timeout_get(flow_add, &val16); of_flow_removed_idle_timeout_set(obj, val16); if (obj->version >= OF_VERSION_1_2) { of_flow_add_hard_timeout_get(flow_add, &val16); of_flow_removed_hard_timeout_set(obj, val16); } return OF_ERROR_NONE; }