/* Returns a buffer owned by the caller that encodes 'features' in the format * required by 'protocol' with the given 'xid'. The caller should append port * information to the buffer with subsequent calls to * ofputil_put_switch_features_port(). */ struct ofpbuf * ofputil_encode_switch_features(const struct ofputil_switch_features *features, enum ofputil_protocol protocol, ovs_be32 xid) { struct ofp_switch_features *osf; struct ofpbuf *b; enum ofp_version version; enum ofpraw raw; version = ofputil_protocol_to_ofp_version(protocol); switch (version) { case OFP10_VERSION: raw = OFPRAW_OFPT10_FEATURES_REPLY; break; case OFP11_VERSION: case OFP12_VERSION: raw = OFPRAW_OFPT11_FEATURES_REPLY; break; case OFP13_VERSION: case OFP14_VERSION: case OFP15_VERSION: raw = OFPRAW_OFPT13_FEATURES_REPLY; break; default: OVS_NOT_REACHED(); } b = ofpraw_alloc_xid(raw, version, xid, 0); osf = ofpbuf_put_zeros(b, sizeof *osf); osf->datapath_id = htonll(features->datapath_id); osf->n_buffers = htonl(features->n_buffers); osf->n_tables = features->n_tables; osf->capabilities = htonl(features->capabilities & ofputil_capabilities_mask(version)); switch (version) { case OFP10_VERSION: if (features->capabilities & OFPUTIL_C_STP) { osf->capabilities |= htonl(OFPC10_STP); } osf->actions = ofpact_bitmap_to_openflow(features->ofpacts, OFP10_VERSION); break; case OFP13_VERSION: case OFP14_VERSION: case OFP15_VERSION: osf->auxiliary_id = features->auxiliary_id; /* fall through */ case OFP11_VERSION: case OFP12_VERSION: if (features->capabilities & OFPUTIL_C_GROUP_STATS) { osf->capabilities |= htonl(OFPC11_GROUP_STATS); } break; default: OVS_NOT_REACHED(); } return b; }
/* Returns an OpenFlow message that, sent on an OpenFlow connection whose * protocol is 'current', at least partly transitions the protocol to 'want'. * Stores in '*next' the protocol that will be in effect on the OpenFlow * connection if the switch processes the returned message correctly. (If * '*next != want' then the caller will have to iterate.) * * If 'current == want', or if it is not possible to transition from 'current' * to 'want' (because, for example, 'current' and 'want' use different OpenFlow * protocol versions), returns NULL and stores 'current' in '*next'. */ struct ofpbuf * ofputil_encode_set_protocol(enum ofputil_protocol current, enum ofputil_protocol want, enum ofputil_protocol *next) { enum ofp_version cur_version, want_version; enum ofputil_protocol cur_base, want_base; bool cur_tid, want_tid; cur_version = ofputil_protocol_to_ofp_version(current); want_version = ofputil_protocol_to_ofp_version(want); if (cur_version != want_version) { *next = current; return NULL; } cur_base = ofputil_protocol_to_base(current); want_base = ofputil_protocol_to_base(want); if (cur_base != want_base) { *next = ofputil_protocol_set_base(current, want_base); switch (want_base) { case OFPUTIL_P_OF10_NXM: case OFPUTIL_P_OF10_STD: return ofputil_encode_nx_set_flow_format(want_base); case OFPUTIL_P_OF11_STD: case OFPUTIL_P_OF12_OXM: case OFPUTIL_P_OF13_OXM: case OFPUTIL_P_OF14_OXM: case OFPUTIL_P_OF15_OXM: case OFPUTIL_P_OF16_OXM: /* There is only one variant of each OpenFlow 1.1+ protocol, and we * verified above that we're not trying to change versions. */ OVS_NOT_REACHED(); case OFPUTIL_P_OF10_STD_TID: case OFPUTIL_P_OF10_NXM_TID: OVS_NOT_REACHED(); } } cur_tid = (current & OFPUTIL_P_TID) != 0; want_tid = (want & OFPUTIL_P_TID) != 0; if (cur_tid != want_tid) { *next = ofputil_protocol_set_tid(current, want_tid); return ofputil_encode_nx_flow_mod_table_id(want_tid); } ovs_assert(current == want); *next = current; return NULL; }
static void ssl_wait(struct stream *stream, enum stream_wait_type wait) { struct ssl_stream *sslv = ssl_stream_cast(stream); switch (wait) { case STREAM_CONNECT: if (stream_connect(stream) != EAGAIN) { poll_immediate_wake(); } else { switch (sslv->state) { case STATE_TCP_CONNECTING: poll_fd_wait(sslv->fd, POLLOUT); break; case STATE_SSL_CONNECTING: /* ssl_connect() called SSL_accept() or SSL_connect(), which * set up the status that we test here. */ poll_fd_wait(sslv->fd, want_to_poll_events(SSL_want(sslv->ssl))); break; default: OVS_NOT_REACHED(); } } break; case STREAM_RECV: if (sslv->rx_want != SSL_NOTHING) { poll_fd_wait(sslv->fd, want_to_poll_events(sslv->rx_want)); } else { poll_immediate_wake(); } break; case STREAM_SEND: if (!sslv->txbuf) { /* We have room in our tx queue. */ poll_immediate_wake(); } else { /* stream_run_wait() will do the right thing; don't bother with * redundancy. */ } break; default: OVS_NOT_REACHED(); } }
/* Reallocates 'b' so that it has exactly 'new_headroom' and 'new_tailroom' * bytes of headroom and tailroom, respectively. */ static void ofpbuf_resize__(struct ofpbuf *b, size_t new_headroom, size_t new_tailroom) { void *new_base, *new_data; size_t new_allocated; new_allocated = new_headroom + b->size + new_tailroom; switch (b->source) { case OFPBUF_MALLOC: if (new_headroom == ofpbuf_headroom(b)) { new_base = xrealloc(b->base, new_allocated); } else { new_base = xmalloc(new_allocated); ofpbuf_copy__(b, new_base, new_headroom, new_tailroom); free(b->base); } break; case OFPBUF_STACK: OVS_NOT_REACHED(); case OFPBUF_STUB: b->source = OFPBUF_MALLOC; new_base = xmalloc(new_allocated); ofpbuf_copy__(b, new_base, new_headroom, new_tailroom); break; default: OVS_NOT_REACHED(); } b->allocated = new_allocated; b->base = new_base; new_data = (char *) new_base + new_headroom; if (b->data != new_data) { if (b->header) { uintptr_t data_delta = (char *) b->header - (char *) b->data; b->header = (char *) new_data + data_delta; } if (b->msg) { uintptr_t data_delta = (char *) b->msg - (char *) b->data; b->msg = (char *) new_data + data_delta; } b->data = new_data; } }
/* Reallocates 'b' so that it has exactly 'new_headroom' and 'new_tailroom' * bytes of headroom and tailroom, respectively. */ static void dp_packet_resize__(struct dp_packet *b, size_t new_headroom, size_t new_tailroom) { void *new_base, *new_data; size_t new_allocated; new_allocated = new_headroom + dp_packet_size(b) + new_tailroom; switch (b->source) { case DPBUF_DPDK: OVS_NOT_REACHED(); case DPBUF_MALLOC: if (new_headroom == dp_packet_headroom(b)) { new_base = xrealloc(dp_packet_base(b), new_allocated); } else { new_base = xmalloc(new_allocated); dp_packet_copy__(b, new_base, new_headroom, new_tailroom); free(dp_packet_base(b)); } break; case DPBUF_STACK: OVS_NOT_REACHED(); case DPBUF_STUB: b->source = DPBUF_MALLOC; new_base = xmalloc(new_allocated); dp_packet_copy__(b, new_base, new_headroom, new_tailroom); break; default: OVS_NOT_REACHED(); } b->allocated = new_allocated; dp_packet_set_base(b, new_base); new_data = (char *) new_base + new_headroom; if (dp_packet_data(b) != new_data) { if (b->frame) { uintptr_t data_delta = (char *) new_data - (char *) dp_packet_data(b); b->frame = (char *) b->frame + data_delta; } dp_packet_set_data(b, new_data); } }
struct ofpbuf * ofputil_encode_bundle_ctrl_request(enum ofp_version ofp_version, struct ofputil_bundle_ctrl_msg *bc) { struct ofpbuf *request; struct ofp14_bundle_ctrl_msg *m; switch (ofp_version) { case OFP10_VERSION: case OFP11_VERSION: case OFP12_VERSION: ovs_fatal(0, "bundles need OpenFlow 1.3 or later " "(\'-O OpenFlow14\')"); case OFP13_VERSION: case OFP14_VERSION: case OFP15_VERSION: request = ofpraw_alloc(ofp_version == OFP13_VERSION ? OFPRAW_ONFT13_BUNDLE_CONTROL : OFPRAW_OFPT14_BUNDLE_CONTROL, ofp_version, 0); m = ofpbuf_put_zeros(request, sizeof *m); m->bundle_id = htonl(bc->bundle_id); m->type = htons(bc->type); m->flags = htons(bc->flags); break; default: OVS_NOT_REACHED(); } return request; }
/* Returns the OpenFlow protocol version number (e.g. OFP10_VERSION, * etc.) that corresponds to 'protocol'. */ enum ofp_version ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol) { switch (protocol) { case OFPUTIL_P_OF10_STD: case OFPUTIL_P_OF10_STD_TID: case OFPUTIL_P_OF10_NXM: case OFPUTIL_P_OF10_NXM_TID: return OFP10_VERSION; case OFPUTIL_P_OF11_STD: return OFP11_VERSION; case OFPUTIL_P_OF12_OXM: return OFP12_VERSION; case OFPUTIL_P_OF13_OXM: return OFP13_VERSION; case OFPUTIL_P_OF14_OXM: return OFP14_VERSION; case OFPUTIL_P_OF15_OXM: return OFP15_VERSION; case OFPUTIL_P_OF16_OXM: return OFP16_VERSION; } OVS_NOT_REACHED(); }
static void lex_token_format_value(const union mf_subvalue *value, enum lex_format format, struct ds *s) { switch (format) { case LEX_F_DECIMAL: ds_put_format(s, "%"PRIu64, ntohll(value->integer)); break; case LEX_F_HEXADECIMAL: mf_format_subvalue(value, s); break; case LEX_F_IPV4: ds_put_format(s, IP_FMT, IP_ARGS(value->ipv4)); break; case LEX_F_IPV6: ipv6_format_addr(&value->ipv6, s); break; case LEX_F_ETHERNET: ds_put_format(s, ETH_ADDR_FMT, ETH_ADDR_ARGS(value->mac)); break; default: OVS_NOT_REACHED(); } }
/* Check whether a fatal signal has occurred and, if so, call the fatal signal * hooks and exit. * * This function is called automatically by poll_block(), but specialized * programs that may not always call poll_block() on a regular basis should * also call it periodically. (Therefore, any function with "block" in its * name should call fatal_signal_run() each time it is called, either directly * or through poll_block(), because such functions can only used by specialized * programs that can afford to block outside their main loop around * poll_block().) */ void fatal_signal_run(void) { sig_atomic_t sig_nr; fatal_signal_init(); sig_nr = stored_sig_nr; if (sig_nr != SIG_ATOMIC_MAX) { char namebuf[SIGNAL_NAME_BUFSIZE]; ovs_mutex_lock(&mutex); VLOG_WARN("terminating with signal %d (%s)", (int)sig_nr, signal_name(sig_nr, namebuf, sizeof namebuf)); call_hooks(sig_nr); /* Re-raise the signal with the default handling so that the program * termination status reflects that we were killed by this signal */ signal(sig_nr, SIG_DFL); raise(sig_nr); ovs_mutex_unlock(&mutex); OVS_NOT_REACHED(); } }
static uint16_t multipath_algorithm(uint32_t hash, enum nx_mp_algorithm algorithm, unsigned int n_links, unsigned int arg) { switch (algorithm) { case NX_MP_ALG_MODULO_N: return hash % n_links; case NX_MP_ALG_HASH_THRESHOLD: if (n_links == 1) { return 0; } return hash / (UINT32_MAX / n_links + 1); case NX_MP_ALG_HRW: return (n_links <= 64 ? algorithm_hrw(hash, n_links) : algorithm_iter_hash(hash, n_links, 0)); case NX_MP_ALG_ITER_HASH: return algorithm_iter_hash(hash, n_links, arg); } OVS_NOT_REACHED(); }
/* Parse a queue status request message into 'oqsr'. * Returns 0 if successful, otherwise an OFPERR_* number. */ enum ofperr ofputil_decode_queue_stats_request(const struct ofp_header *request, struct ofputil_queue_stats_request *oqsr) { switch ((enum ofp_version)request->version) { case OFP16_VERSION: case OFP15_VERSION: case OFP14_VERSION: case OFP13_VERSION: case OFP12_VERSION: case OFP11_VERSION: { const struct ofp11_queue_stats_request *qsr11 = ofpmsg_body(request); oqsr->queue_id = ntohl(qsr11->queue_id); return ofputil_port_from_ofp11(qsr11->port_no, &oqsr->port_no); } case OFP10_VERSION: { const struct ofp10_queue_stats_request *qsr10 = ofpmsg_body(request); oqsr->queue_id = ntohl(qsr10->queue_id); oqsr->port_no = u16_to_ofp(ntohs(qsr10->port_no)); /* OF 1.0 uses OFPP_ALL for OFPP_ANY */ if (oqsr->port_no == OFPP_ALL) { oqsr->port_no = OFPP_ANY; } return 0; } default: OVS_NOT_REACHED(); } }
static void odp_execute_sample(void *dp, struct dpif_packet *packet, bool steal, struct pkt_metadata *md, const struct nlattr *action, odp_execute_cb dp_execute_action, bool more_actions) { const struct nlattr *subactions = NULL; const struct nlattr *a; size_t left; NL_NESTED_FOR_EACH_UNSAFE (a, left, action) { int type = nl_attr_type(a); switch ((enum ovs_sample_attr) type) { case OVS_SAMPLE_ATTR_PROBABILITY: if (random_uint32() >= nl_attr_get_u32(a)) { return; } break; case OVS_SAMPLE_ATTR_ACTIONS: subactions = a; break; case OVS_SAMPLE_ATTR_UNSPEC: case __OVS_SAMPLE_ATTR_MAX: default: OVS_NOT_REACHED(); } }
/* Returns the equivalent of 'protocol' with the Nicira flow_mod_table_id * extension turned on or off if 'enable' is true or false, respectively. * * This extension is only useful for protocols whose "standard" version does * not allow specific tables to be modified. In particular, this is true of * OpenFlow 1.0. In later versions of OpenFlow, a flow_mod request always * specifies a table ID and so there is no need for such an extension. When * 'protocol' is such a protocol that doesn't need a flow_mod_table_id * extension, this function just returns its 'protocol' argument unchanged * regardless of the value of 'enable'. */ enum ofputil_protocol ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable) { switch (protocol) { case OFPUTIL_P_OF10_STD: case OFPUTIL_P_OF10_STD_TID: return enable ? OFPUTIL_P_OF10_STD_TID : OFPUTIL_P_OF10_STD; case OFPUTIL_P_OF10_NXM: case OFPUTIL_P_OF10_NXM_TID: return enable ? OFPUTIL_P_OF10_NXM_TID : OFPUTIL_P_OF10_NXM; case OFPUTIL_P_OF11_STD: return OFPUTIL_P_OF11_STD; case OFPUTIL_P_OF12_OXM: return OFPUTIL_P_OF12_OXM; case OFPUTIL_P_OF13_OXM: return OFPUTIL_P_OF13_OXM; case OFPUTIL_P_OF14_OXM: return OFPUTIL_P_OF14_OXM; case OFPUTIL_P_OF15_OXM: return OFPUTIL_P_OF15_OXM; case OFPUTIL_P_OF16_OXM: return OFPUTIL_P_OF16_OXM; default: OVS_NOT_REACHED(); } }
static bool ovsdb_clause_evaluate(const struct ovsdb_row *row, const struct ovsdb_clause *c) { const struct ovsdb_datum *field = &row->fields[c->column->index]; const struct ovsdb_datum *arg = &c->arg; const struct ovsdb_type *type = &c->column->type; if (ovsdb_type_is_scalar(type)) { int cmp = ovsdb_atom_compare_3way(&field->keys[0], &arg->keys[0], type->key.type); switch (c->function) { case OVSDB_F_LT: return cmp < 0; case OVSDB_F_LE: return cmp <= 0; case OVSDB_F_EQ: case OVSDB_F_INCLUDES: return cmp == 0; case OVSDB_F_NE: case OVSDB_F_EXCLUDES: return cmp != 0; case OVSDB_F_GE: return cmp >= 0; case OVSDB_F_GT: return cmp > 0; } } else { switch (c->function) { case OVSDB_F_EQ: return ovsdb_datum_equals(field, arg, type); case OVSDB_F_NE: return !ovsdb_datum_equals(field, arg, type); case OVSDB_F_INCLUDES: return ovsdb_datum_includes_all(arg, field, type); case OVSDB_F_EXCLUDES: return ovsdb_datum_excludes_all(arg, field, type); case OVSDB_F_LT: case OVSDB_F_LE: case OVSDB_F_GE: case OVSDB_F_GT: OVS_NOT_REACHED(); } } OVS_NOT_REACHED(); }
static short int want_to_poll_events(int want) { switch (want) { case SSL_NOTHING: OVS_NOT_REACHED(); case SSL_READING: return POLLIN; case SSL_WRITING: return POLLOUT; default: OVS_NOT_REACHED(); } }
static size_t lex_token_n_zeros(enum lex_format format) { switch (format) { case LEX_F_DECIMAL: return offsetof(union mf_subvalue, integer); case LEX_F_HEXADECIMAL: return 0; case LEX_F_IPV4: return offsetof(union mf_subvalue, ipv4); case LEX_F_IPV6: return offsetof(union mf_subvalue, ipv6); case LEX_F_ETHERNET: return offsetof(union mf_subvalue, mac); default: OVS_NOT_REACHED(); } }
const char * ofputil_frag_handling_to_string(enum ofputil_frag_handling frag) { switch (frag) { case OFPUTIL_FRAG_NORMAL: return "normal"; case OFPUTIL_FRAG_DROP: return "drop"; case OFPUTIL_FRAG_REASM: return "reassemble"; case OFPUTIL_FRAG_NX_MATCH: return "nx-match"; } OVS_NOT_REACHED(); }
static void idl_loop_commit_and_wait(struct idl_loop *loop) { if (loop->open_txn) { loop->committing_txn = loop->open_txn; loop->open_txn = NULL; loop->precommit_seqno = ovsdb_idl_get_seqno(loop->idl); } struct ovsdb_idl_txn *txn = loop->committing_txn; if (txn) { enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(txn); if (status != TXN_INCOMPLETE) { switch (status) { case TXN_TRY_AGAIN: /* We want to re-evaluate the database when it's changed from * the contents that it had when we started the commit. (That * might have already happened.) */ loop->skip_seqno = loop->precommit_seqno; if (ovsdb_idl_get_seqno(loop->idl) != loop->skip_seqno) { poll_immediate_wake(); } break; case TXN_SUCCESS: /* If the database has already changed since we started the * commit, re-evaluate it immediately to avoid missing a change * for a while. */ if (ovsdb_idl_get_seqno(loop->idl) != loop->precommit_seqno) { poll_immediate_wake(); } break; case TXN_UNCHANGED: case TXN_ABORTED: case TXN_NOT_LOCKED: case TXN_ERROR: break; case TXN_UNCOMMITTED: case TXN_INCOMPLETE: OVS_NOT_REACHED(); } ovsdb_idl_txn_destroy(txn); loop->committing_txn = NULL; } } ovsdb_idl_wait(loop->idl); }
/* Forks, then: * * - In the parent, waits for the child to signal that it has completed its * startup sequence. Then stores -1 in '*fdp' and returns the child's * pid in '*child_pid' argument. * * - In the child, stores a fd in '*fdp' and returns 0 through '*child_pid' * argument. The caller should pass the fd to fork_notify_startup() after * it finishes its startup sequence. * * Returns 0 on success. If something goes wrong and child process was not * able to signal its readiness by calling fork_notify_startup(), then this * function returns -1. However, even in case of failure it still sets child * process id in '*child_pid'. */ static int fork_and_wait_for_startup(int *fdp, pid_t *child_pid) { int fds[2]; pid_t pid; int ret = 0; xpipe(fds); pid = fork_and_clean_up(); if (pid > 0) { /* Running in parent process. */ size_t bytes_read; char c; close(fds[1]); if (read_fully(fds[0], &c, 1, &bytes_read) != 0) { int retval; int status; do { retval = waitpid(pid, &status, 0); } while (retval == -1 && errno == EINTR); if (retval == pid) { if (WIFEXITED(status) && WEXITSTATUS(status)) { /* Child exited with an error. Convey the same error * to our parent process as a courtesy. */ exit(WEXITSTATUS(status)); } else { char *status_msg = process_status_msg(status); VLOG_ERR("fork child died before signaling startup (%s)", status_msg); ret = -1; } } else if (retval < 0) { VLOG_FATAL("waitpid failed (%s)", ovs_strerror(errno)); } else { OVS_NOT_REACHED(); } } close(fds[0]); *fdp = -1; } else if (!pid) { /* Running in child process. */ close(fds[0]); *fdp = fds[1]; } *child_pid = pid; return ret; }
/* Converts an OFPST_QUEUE_STATS reply in 'msg' into an abstract * ofputil_queue_stats in 'qs'. * * Multiple OFPST_QUEUE_STATS replies can be packed into a single OpenFlow * message. Calling this function multiple times for a single 'msg' iterates * through the replies. The caller must initially leave 'msg''s layer pointers * null and not modify them between calls. * * Returns 0 if successful, EOF if no replies were left in this 'msg', * otherwise a positive errno value. */ int ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg) { enum ofperr error; enum ofpraw raw; error = (msg->header ? ofpraw_decode(&raw, msg->header) : ofpraw_pull(&raw, msg)); if (error) { return error; } if (!msg->size) { return EOF; } else if (raw == OFPRAW_OFPST14_QUEUE_REPLY) { return ofputil_pull_ofp14_queue_stats(qs, msg); } else if (raw == OFPRAW_OFPST13_QUEUE_REPLY) { const struct ofp13_queue_stats *qs13; qs13 = ofpbuf_try_pull(msg, sizeof *qs13); if (!qs13) { goto bad_len; } return ofputil_queue_stats_from_ofp13(qs, qs13); } else if (raw == OFPRAW_OFPST11_QUEUE_REPLY) { const struct ofp11_queue_stats *qs11; qs11 = ofpbuf_try_pull(msg, sizeof *qs11); if (!qs11) { goto bad_len; } return ofputil_queue_stats_from_ofp11(qs, qs11); } else if (raw == OFPRAW_OFPST10_QUEUE_REPLY) { const struct ofp10_queue_stats *qs10; qs10 = ofpbuf_try_pull(msg, sizeof *qs10); if (!qs10) { goto bad_len; } return ofputil_queue_stats_from_ofp10(qs, qs10); } else { OVS_NOT_REACHED(); } bad_len: VLOG_WARN_RL(&rl, "OFPST_QUEUE reply has %"PRIu32" leftover " "bytes at end", msg->size); return OFPERR_OFPBRC_BAD_LEN; }
/* Returns an NXT_SET_FLOW_FORMAT message that can be used to set the flow * format to 'protocol'. */ struct ofpbuf * ofputil_encode_nx_set_flow_format(enum ofputil_protocol protocol) { struct ofpbuf *msg = ofpraw_alloc(OFPRAW_NXT_SET_FLOW_FORMAT, OFP10_VERSION, 0); ovs_be32 *nxff = ofpbuf_put_uninit(msg, sizeof *nxff); if (protocol == OFPUTIL_P_OF10_STD) { *nxff = htonl(NXFF_OPENFLOW10); } else if (protocol == OFPUTIL_P_OF10_NXM) { *nxff = htonl(NXFF_NXM); } else { OVS_NOT_REACHED(); } return msg; }
static const char * pop_tunnel_name(uint32_t *type) { if (*type & GENEVE) { *type &= ~GENEVE; return "geneve"; } else if (*type & STT) { *type &= ~STT; return "stt"; } else if (*type & VXLAN) { *type &= ~VXLAN; return "vxlan"; } OVS_NOT_REACHED(); }
/* Executes 'bundle' on 'flow'. Sets fields in 'wc' that were used to * calculate the result. Uses 'slave_enabled' to determine if the slave * designated by 'ofp_port' is up. Returns the chosen slave, or * OFPP_NONE if none of the slaves are acceptable. */ ofp_port_t bundle_execute(const struct ofpact_bundle *bundle, const struct flow *flow, struct flow_wildcards *wc, bool (*slave_enabled)(ofp_port_t ofp_port, void *aux), void *aux) { switch (bundle->algorithm) { case NX_BD_ALG_HRW: return execute_hrw(bundle, flow, wc, slave_enabled, aux); case NX_BD_ALG_ACTIVE_BACKUP: return execute_ab(bundle, slave_enabled, aux); default: OVS_NOT_REACHED(); } }
static bool oftrace_node_type_is_terminal(enum oftrace_node_type type) { switch (type) { case OFT_ACTION: case OFT_DETAIL: case OFT_WARN: case OFT_ERROR: return true; case OFT_BRIDGE: case OFT_TABLE: case OFT_THAW: return false; } OVS_NOT_REACHED(); }
/* Returns a string that represents 'protocols'. The return value might be a * comma-separated list if 'protocols' doesn't have a simple name. The return * value is "none" if 'protocols' is 0. * * The caller must free the returned string (with free()). */ char * ofputil_protocols_to_string(enum ofputil_protocol protocols) { struct ds s; ovs_assert(!(protocols & ~OFPUTIL_P_ANY)); if (protocols == 0) { return xstrdup("none"); } ds_init(&s); while (protocols) { const struct proto_abbrev *p; int i; if (s.length) { ds_put_char(&s, ','); } for (p = proto_abbrevs; p < &proto_abbrevs[N_PROTO_ABBREVS]; p++) { if ((protocols & p->protocol) == p->protocol) { ds_put_cstr(&s, p->name); protocols &= ~p->protocol; goto match; } } for (i = 0; i < CHAR_BIT * sizeof(enum ofputil_protocol); i++) { enum ofputil_protocol bit = 1u << i; if (protocols & bit) { ds_put_cstr(&s, ofputil_protocol_to_string(bit)); protocols &= ~bit; goto match; } } OVS_NOT_REACHED(); match: ; } return ds_steal_cstr(&s); }
/* Constructs and returns the beginning of a reply to * OFPT_QUEUE_GET_CONFIG_REQUEST or OFPMP_QUEUE_DESC request 'oh'. The caller * may append information about individual queues with * ofputil_append_queue_get_config_reply(). */ void ofputil_start_queue_get_config_reply(const struct ofp_header *request, struct ovs_list *replies) { struct ofpbuf *reply; ofp_port_t port; uint32_t queue; ovs_assert(!ofputil_decode_queue_get_config_request(request, &port, &queue)); enum ofpraw raw = ofpraw_decode_assert(request); switch ((int) raw) { case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST: reply = ofpraw_alloc_reply(OFPRAW_OFPT10_QUEUE_GET_CONFIG_REPLY, request, 0); struct ofp10_queue_get_config_reply *qgcr10 = ofpbuf_put_zeros(reply, sizeof *qgcr10); qgcr10->port = htons(ofp_to_u16(port)); break; case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST: reply = ofpraw_alloc_reply(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY, request, 0); struct ofp11_queue_get_config_reply *qgcr11 = ofpbuf_put_zeros(reply, sizeof *qgcr11); qgcr11->port = ofputil_port_to_ofp11(port); break; case OFPRAW_OFPST14_QUEUE_DESC_REQUEST: reply = ofpraw_alloc_stats_reply(request, 0); break; default: OVS_NOT_REACHED(); } ovs_list_init(replies); ovs_list_push_back(replies, &reply->list_node); }
const char * ofputil_version_to_string(enum ofp_version ofp_version) { switch (ofp_version) { case OFP10_VERSION: return "OpenFlow10"; case OFP11_VERSION: return "OpenFlow11"; case OFP12_VERSION: return "OpenFlow12"; case OFP13_VERSION: return "OpenFlow13"; case OFP14_VERSION: return "OpenFlow14"; case OFP15_VERSION: return "OpenFlow15"; case OFP16_VERSION: return "OpenFlow16"; default: OVS_NOT_REACHED(); } }
/* Parses OFPT_QUEUE_GET_CONFIG request 'oh', storing the port specified by the * request into '*port'. Returns 0 if successful, otherwise an OpenFlow error * code. */ enum ofperr ofputil_decode_queue_get_config_request(const struct ofp_header *oh, ofp_port_t *port, uint32_t *queue) { const struct ofp10_queue_get_config_request *qgcr10; const struct ofp11_queue_get_config_request *qgcr11; const struct ofp14_queue_desc_request *qdr14; struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); enum ofpraw raw = ofpraw_pull_assert(&b); switch ((int) raw) { case OFPRAW_OFPT10_QUEUE_GET_CONFIG_REQUEST: qgcr10 = b.data; *port = u16_to_ofp(ntohs(qgcr10->port)); *queue = OFPQ_ALL; break; case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST: qgcr11 = b.data; *queue = OFPQ_ALL; enum ofperr error = ofputil_port_from_ofp11(qgcr11->port, port); if (error || *port == OFPP_ANY) { return error; } break; case OFPRAW_OFPST14_QUEUE_DESC_REQUEST: qdr14 = b.data; *queue = ntohl(qdr14->queue); return ofputil_port_from_ofp11(qdr14->port, port); default: OVS_NOT_REACHED(); } return (ofp_to_u16(*port) < ofp_to_u16(OFPP_MAX) ? 0 : OFPERR_OFPQOFC_BAD_PORT); }
/* Returns 'new_base' with any extensions taken from 'cur'. */ enum ofputil_protocol ofputil_protocol_set_base(enum ofputil_protocol cur, enum ofputil_protocol new_base) { bool tid = (cur & OFPUTIL_P_TID) != 0; switch (new_base) { case OFPUTIL_P_OF10_STD: case OFPUTIL_P_OF10_STD_TID: return ofputil_protocol_set_tid(OFPUTIL_P_OF10_STD, tid); case OFPUTIL_P_OF10_NXM: case OFPUTIL_P_OF10_NXM_TID: return ofputil_protocol_set_tid(OFPUTIL_P_OF10_NXM, tid); case OFPUTIL_P_OF11_STD: return ofputil_protocol_set_tid(OFPUTIL_P_OF11_STD, tid); case OFPUTIL_P_OF12_OXM: return ofputil_protocol_set_tid(OFPUTIL_P_OF12_OXM, tid); case OFPUTIL_P_OF13_OXM: return ofputil_protocol_set_tid(OFPUTIL_P_OF13_OXM, tid); case OFPUTIL_P_OF14_OXM: return ofputil_protocol_set_tid(OFPUTIL_P_OF14_OXM, tid); case OFPUTIL_P_OF15_OXM: return ofputil_protocol_set_tid(OFPUTIL_P_OF15_OXM, tid); case OFPUTIL_P_OF16_OXM: return ofputil_protocol_set_tid(OFPUTIL_P_OF16_OXM, tid); default: OVS_NOT_REACHED(); } }
/* Encode a queue stats request for 'oqsr', the encoded message * will be for OpenFlow version 'ofp_version'. Returns message * as a struct ofpbuf. Returns encoded message on success, NULL on error. */ struct ofpbuf * ofputil_encode_queue_stats_request( enum ofp_version ofp_version, const struct ofputil_queue_stats_request *oqsr) { struct ofpbuf *request; switch (ofp_version) { case OFP11_VERSION: case OFP12_VERSION: case OFP13_VERSION: case OFP14_VERSION: case OFP15_VERSION: case OFP16_VERSION: { struct ofp11_queue_stats_request *req; request = ofpraw_alloc(OFPRAW_OFPST11_QUEUE_REQUEST, ofp_version, 0); req = ofpbuf_put_zeros(request, sizeof *req); req->port_no = ofputil_port_to_ofp11(oqsr->port_no); req->queue_id = htonl(oqsr->queue_id); break; } case OFP10_VERSION: { struct ofp10_queue_stats_request *req; request = ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST, ofp_version, 0); req = ofpbuf_put_zeros(request, sizeof *req); /* OpenFlow 1.0 needs OFPP_ALL instead of OFPP_ANY */ req->port_no = htons(ofp_to_u16(oqsr->port_no == OFPP_ANY ? OFPP_ALL : oqsr->port_no)); req->queue_id = htonl(oqsr->queue_id); break; } default: OVS_NOT_REACHED(); } return request; }