/* Sends a packet to the controller in a packet_in message */ static void send_packet_to_controller(struct pipeline *pl, struct packet *pkt, uint8_t table_id, uint8_t reason) { dp_buffers_save(pl->dp->buffers, pkt); { struct ofl_msg_packet_in msg = {{.type = OFPT_PACKET_IN}, .buffer_id = pkt->buffer_id, .total_len = pkt->buffer->size, .reason = reason, .table_id = table_id, .data_length = MIN(pl->dp->config.miss_send_len, pkt->buffer->size), .data = pkt->buffer->data}; struct ofl_match *m = xmalloc (sizeof(struct ofl_match)); ofl_structs_match_init(m); /* In this implementation the fields in_port and in_phy_port always will be the same, because we are not considering logical ports */ ofl_structs_match_put32(m,OXM_OF_IN_PORT,pkt->in_port); ofl_structs_match_put32(m,OXM_OF_IN_PHY_PORT,pkt->in_port); msg.match = (struct ofl_match_header*)m; dp_send_message(pl->dp, (struct ofl_msg_header *)&msg, NULL); }
/* Sends a packet to the controller in a packet_in message */ static void send_packet_to_controller(struct pipeline *pl, struct packet *pkt, uint8_t table_id, uint8_t reason) { struct ofl_msg_packet_in msg; struct ofl_match *m; msg.header.type = OFPT_PACKET_IN; msg.total_len = pkt->buffer->size; msg.reason = reason; msg.table_id = table_id; msg.cookie = 0xffffffffffffffff; msg.data = pkt->buffer->data; /* A max_len of OFPCML_NO_BUFFER means that the complete packet should be sent, and it should not be buffered.*/ if (pl->dp->config.miss_send_len != OFPCML_NO_BUFFER){ dp_buffers_save(pl->dp->buffers, pkt); msg.buffer_id = pkt->buffer_id; msg.data_length = MIN(pl->dp->config.miss_send_len, pkt->buffer->size); }else { msg.buffer_id = OFP_NO_BUFFER; msg.data_length = pkt->buffer->size; } m = xmalloc (sizeof(struct ofl_match)); ofl_structs_match_init(m); /* In this implementation the fields in_port and in_phy_port always will be the same, because we are not considering logical ports */ ofl_structs_match_convert_pktf2oflm(&pkt->handle_std->match.match_fields, m); msg.match = (struct ofl_match_header*)m; dp_send_message(pl->dp, (struct ofl_msg_header *)&msg, NULL); ofl_structs_free_match((struct ofl_match_header* ) m, NULL); }
void flow_entry_remove(struct flow_entry *entry, uint8_t reason) { if (entry->send_removed) { flow_entry_update(entry); { struct ofl_msg_flow_removed msg = {{.type = OFPT_FLOW_REMOVED}, .reason = reason, .stats = entry->stats}; dp_send_message(entry->dp, (struct ofl_msg_header *)&msg, NULL); }
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) {
/* Handles barrier request messages. */ static ofl_err handle_control_barrier_request(struct datapath *dp, struct ofl_msg_header *msg, const struct sender *sender) { /* Note: the implementation is single-threaded, so a barrier request can simply be replied. */ struct ofl_msg_header reply = {.type = OFPT_BARRIER_REPLY}; dp_send_message(dp, (struct ofl_msg_header *)&reply, sender); ofl_msg_free(msg, dp->exp); return 0; }
/* Sends a packet to the controller in a packet_in message */ static void send_packet_to_controller(struct pipeline *pl, struct packet *pkt, uint8_t table_id, uint8_t reason) { dp_buffers_save(pl->dp->buffers, pkt); { struct ofl_msg_packet_in msg = {{.type = OFPT_PACKET_IN}, .buffer_id = pkt->buffer_id, .in_port = pkt->in_port, .in_phy_port = pkt->in_port, // TODO: how to get phy port for v.port? .total_len = pkt->buffer->size, .reason = reason, .table_id = table_id, .data_length = MIN(pl->dp->config.miss_send_len, pkt->buffer->size), .data = pkt->buffer->data}; dp_send_message(pl->dp, (struct ofl_msg_header *)&msg, NULL); }
static void port_status_check(struct datapath *dp) { #define OTN_INTERFACES_FILE "/tmp/otn_interfaces.ini" #define BUFFSIZE 1024 uint32_t port_no; char command[BUFFSIZE]; char buff[BUFFSIZE]; struct sw_port *port = NULL; FILE *fp = NULL; for (port_no = 1; port_no < DP_MAX_PORTS; port_no++) { port = &dp->ports[port_no]; if (port && port->conf) { sprintf(command, "grep %s " OTN_INTERFACES_FILE " | cut -d',' -f2 ", port->conf->name); fp = popen(command, "r"); memset(buff, 0, BUFFSIZE); if (fp == NULL) { printf( "Failed to run command: %s", strerror(errno)); continue; } if (fgets(buff, sizeof(buff), fp) != NULL) { buff[strlen(buff) - 1] = '\0'; if ((strcmp(buff, "up") == 0) && !(port->conf->state & OFPPS_LIVE) ) { port->conf->state = 0x00000000 | OFPPS_LIVE; } else if ((strcmp(buff, "down") == 0) && !(port->conf->state & OFPPS_LINK_DOWN)) { port->conf->state = 0x00000000 | OFPPS_LINK_DOWN; } else { goto close_fp; } /* Send the port status */ struct ofl_msg_port_status status_msg = {{.type = OFPT_PORT_STATUS}, .reason = OFPPR_MODIFY, .desc = port->conf}; dp_send_message(dp, (struct ofl_msg_header *)&status_msg, NULL/*sender*/); }
/* 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; }