void dp_run(struct datapath *dp) { time_t now; struct remote *r, *rn; size_t i; struct timeval time_check; uint64_t sched_sec; uint32_t sched_nsec; if (now != dp->last_timeout) { dp->last_timeout = now; meter_table_add_tokens(dp->meters); pipeline_timeout(dp->pipeline); } //TIME_EXTENTION_EXP gettimeofday(&time_check, 0); if((bundle_time_ctl.ctl.flags!=0) & (!bundle_time_ctl.discard) ){ sched_sec = bundle_time_ctl.sched_time.seconds; sched_nsec = bundle_time_ctl.sched_time.nanoseconds; if((time_check.tv_sec >sched_sec) || ((time_check.tv_sec == sched_sec) && ((time_check.tv_usec*1000) >= sched_nsec))){ printf("Commit Bundle in time sched :%lu.%09u\n",sched_sec,sched_nsec); printf("Commit Bundle in time actual:%u.%09u\n",time_check.tv_sec,time_check.tv_usec*1000); bundle_time_ctl.commiting_now=1; // shutting down only time flag bundle_time_ctl.ctl.flags=bundle_time_ctl.ctl.flags & 0xFFFB; struct sender sender = {.remote = bundle_time_ctl.remote, .conn_id = bundle_time_ctl.conn_id , .xid = bundle_time_ctl.xid}; handle_control_msg(dp, &bundle_time_ctl.ctl, &sender); bundle_time_ctl.commiting_now=0; } }
static void remote_rconn_run(struct datapath *dp, struct remote *r, uint8_t conn_id) { struct rconn *rconn; ofl_err error; size_t i; if (conn_id == MAIN_CONNECTION) rconn = r->rconn; else if (conn_id == PTIN_CONNECTION) rconn = r->rconn_aux; rconn_run(rconn); /* Do some remote processing, but cap it at a reasonable amount so that * other processing doesn't starve. */ for (i = 0; i < 50; i++) { if (!r->cb_dump) { struct ofpbuf *buffer; buffer = rconn_recv(rconn); if (buffer == NULL) { break; } else { struct ofl_msg_header *msg; struct sender sender = {.remote = r, .conn_id = conn_id}; error = ofl_msg_unpack(buffer->data, buffer->size, &msg, &(sender.xid), dp->exp); if (!error) { error = handle_control_msg(dp, msg, &sender); if (error) { ofl_msg_free(msg, dp->exp); } } if (error) { struct ofl_msg_error err = {{.type = OFPT_ERROR}, .type = ofl_error_type(error), .code = ofl_error_code(error), .data_length = buffer->size, .data = buffer->data}; dp_send_message(dp, (struct ofl_msg_header *)&err, &sender); } ofpbuf_delete(buffer); } } else { if (r->n_txq < TXQ_LIMIT) {
/* Commit operation. */ static ofl_err bundle_commit(struct datapath *dp, struct bundle_table *table, uint32_t bundle_id, uint16_t flags, const struct sender *sender) { struct bundle_table_entry *entry; struct bundle_message *bundle_msg; struct ofl_msg_header *msg; uint32_t xid; ofl_err error; ofl_err last_error = ofl_error(OFPET_BUNDLE_FAILED, OFPBFC_BAD_ID); /* Find and process commit operation for bundle ID */ entry = bundle_table_entry_find(table, bundle_id); if (entry != NULL) { /* Ensure flags are consistent with flags specified previously */ if (entry->flags != flags) { last_error = ofl_error(OFPET_BUNDLE_FAILED, OFPBFC_BAD_FLAGS); } else { /* Save state in case failure occurs */ last_error = 0; dp_save_state(dp); /* Commit all messages in bundle, stopping at first error */ LIST_FOR_EACH (bundle_msg, struct bundle_message, node, &entry->bundle_message_list) { VLOG_DBG_RL(LOG_MODULE, &rl, "Commit of message with type %u and length %u\n", bundle_msg->message->type, ntohs(bundle_msg->message->length)); error = ofl_msg_unpack((uint8_t *)bundle_msg->message, ntohs(bundle_msg->message->length), &msg, &xid, dp->exp); if (!error) { /* This prototype only properly supports bundling of * messages that do not generate replies (other than * error replies). TODO: keep replies in a holding * area and only release them to the controller when * the commit succeeds. */ error = handle_control_msg(dp, msg, sender); if (error) { ofl_msg_free(msg, dp->exp); } } if (error) { last_error = error; break; } } /* Restore state if failures occurred */ if (last_error) { dp_restore_state(dp); } else { /* TODO free memory used to save state without restoring * (not required currently as variables used to save/restore * state are re-used) */ } /* We need to generate the error ourselves. The spec say that * the error need to refer to the offending message in the budle. * If we just return the error code, the error message would refer * to the commit message. */ if (last_error) { struct sender orig_sender = {.remote = sender->remote, .conn_id = sender->conn_id, .xid = xid}; struct ofl_msg_error orig_err = {{.type = OFPT_ERROR}, .type = ofl_error_type(last_error), .code = ofl_error_code(last_error), .data_length = ntohs(bundle_msg->message->length), .data = (uint8_t *)bundle_msg->message}; dp_send_message(dp, (struct ofl_msg_header *)&orig_err, &orig_sender); /* Trigger second error message. */ last_error = ofl_error(OFPET_BUNDLE_FAILED, OFPBFC_MSG_FAILED); } } /* Whether or not commit succeeded: free entry for bundle ID */ bundle_table_entry_destroy(entry); } return last_error; }