#include "ofproto-dpif-ipfix.h"
#include "ofproto-dpif-mirror.h"
#include "ofproto-dpif-monitor.h"
+#include "ofproto-dpif-rid.h"
#include "ofproto-dpif-sflow.h"
#include "ofproto-dpif-upcall.h"
#include "ofproto-dpif-xlate.h"
bool recv_set_enable; /* Enables or disables receiving packets. */
+ struct recirc_id_pool *rid_pool; /* Recirculation ID pool. */
+
/* True if the datapath supports variable-length
* OVS_USERSPACE_ATTR_USERDATA in OVS_ACTION_ATTR_USERSPACE actions.
* False if the datapath supports only 8-byte (or shorter) userdata. */
free(pin);
}
}
+
+/* The default "table-miss" behaviour for OpenFlow1.3+ is to drop the
+ * packet rather than to send the packet to the controller.
+ *
+ * This function returns false to indicate that a packet_in message
+ * for a "table-miss" should be sent to at least one controller.
+ * False otherwise. */
+bool
+ofproto_dpif_wants_packet_in_on_miss(struct ofproto_dpif *ofproto)
+{
+ return connmgr_wants_packet_in_on_miss(ofproto->up.connmgr);
+}
\f
/* Factory functions. */
ovs_rwlock_destroy(&backer->odp_to_ofport_lock);
hmap_destroy(&backer->odp_to_ofport_map);
shash_find_and_delete(&all_dpif_backers, backer->type);
+ recirc_id_pool_destroy(backer->rid_pool);
free(backer->type);
dpif_close(backer->dpif);
-
free(backer);
}
struct shash_node *node;
struct list garbage_list;
struct odp_garbage *garbage, *next;
+
struct sset names;
char *backer_name;
const char *name;
}
backer->variable_length_userdata = check_variable_length_userdata(backer);
backer->max_mpls_depth = check_max_mpls_depth(backer);
+ backer->rid_pool = recirc_id_pool_create();
if (backer->recv_set_enable) {
udpif_set_threads(backer->udpif, n_handlers, n_revalidators);
/* Execute the actions. On older datapaths this fails with ERANGE, on
* newer datapaths it succeeds. */
- execute.actions = actions.data;
- execute.actions_len = actions.size;
+ execute.actions = ofpbuf_data(&actions);
+ execute.actions_len = ofpbuf_size(&actions);
execute.packet = &packet;
execute.md = PKT_METADATA_INITIALIZER(0);
execute.needs_help = false;
odp_flow_key_from_flow(&key, &flow, 0);
error = dpif_flow_put(backer->dpif, DPIF_FP_CREATE | DPIF_FP_MODIFY,
- key.data, key.size, NULL, 0, NULL, 0, NULL);
+ ofpbuf_data(&key), ofpbuf_size(&key), NULL, 0, NULL, 0, NULL);
if (error && error != EEXIST) {
if (error != EINVAL) {
VLOG_WARN("%s: MPLS stack length feature probe failed (%s)",
break;
}
- error = dpif_flow_del(backer->dpif, key.data, key.size, NULL);
+ error = dpif_flow_del(backer->dpif, ofpbuf_data(&key), ofpbuf_size(&key), NULL);
if (error) {
VLOG_WARN("%s: failed to delete MPLS feature probe flow",
dpif_name(backer->dpif));
fm.buffer_id = 0;
fm.out_port = 0;
fm.flags = 0;
- fm.ofpacts = ofpacts->data;
- fm.ofpacts_len = ofpacts->size;
+ fm.ofpacts = ofpbuf_data(ofpacts);
+ fm.ofpacts_len = ofpbuf_size(ofpacts);
error = ofproto_flow_mod(&ofproto->up, &fm);
if (error) {
VLOG_WARN_RL(&rl, "%s: cannot send BPDU on unknown port %d",
ofproto->up.name, port_num);
} else {
- struct eth_header *eth = pkt->l2;
+ struct eth_header *eth = ofpbuf_l2(pkt);
netdev_get_etheraddr(ofport->up.netdev, eth->eth_src);
if (eth_addr_is_zero(eth->eth_src)) {
learning_packet = bond_compose_learning_packet(bundle->bond,
e->mac, e->vlan,
&port_void);
- learning_packet->private_p = port_void;
+ /* Temporarily use 'frame' as a private pointer (see below). */
+ ovs_assert(learning_packet->frame == ofpbuf_data(learning_packet));
+ learning_packet->frame = port_void;
list_push_back(&packets, &learning_packet->list_node);
}
}
error = n_packets = n_errors = 0;
LIST_FOR_EACH (learning_packet, list_node, &packets) {
int ret;
+ void *port_void = learning_packet->frame;
- ret = ofproto_dpif_send_packet(learning_packet->private_p, learning_packet);
+ /* Restore 'frame'. */
+ learning_packet->frame = ofpbuf_data(learning_packet);
+ ret = ofproto_dpif_send_packet(port_void, learning_packet);
if (ret) {
error = ret;
n_errors++;
if (in_port == OFPP_NONE) {
in_port = OFPP_LOCAL;
}
- execute.actions = xout.odp_actions.data;
- execute.actions_len = xout.odp_actions.size;
+ execute.actions = ofpbuf_data(&xout.odp_actions);
+ execute.actions_len = ofpbuf_size(&xout.odp_actions);
execute.packet = packet;
execute.md.tunnel = flow->tunnel;
execute.md.skb_priority = flow->skb_priority;
case RULE_DPIF_LOOKUP_VERDICT_DROP:
config = OFPUTIL_PC_NO_PACKET_IN;
break;
+ case RULE_DPIF_LOOKUP_VERDICT_DEFAULT:
+ if (!connmgr_wants_packet_in_on_miss(ofproto->up.connmgr)) {
+ config = OFPUTIL_PC_NO_PACKET_IN;
+ }
+ break;
default:
OVS_NOT_REACHED();
}
*
* - RULE_DPIF_LOOKUP_VERDICT_MATCH if a rule (in '*rule') was found.
*
- * - RULE_DPIF_LOOKUP_VERDICT_DROP if no rule was found and a table miss
- * configuration specified that the packet should be dropped in this
- * case. (This occurs only if 'honor_table_miss' is true, because only in
- * this case does the table miss configuration matter.)
+ * - RULE_OFPTC_TABLE_MISS_CONTROLLER if no rule was found and either:
+ * + 'honor_table_miss' is false
+ * + a table miss configuration specified that the packet should be
+ *
+ * - RULE_DPIF_LOOKUP_VERDICT_DROP if no rule was found, 'honor_table_miss'
+ * is true and a table miss configuration specified that the packet
+ * should be dropped in this case.
*
- * - RULE_DPIF_LOOKUP_VERDICT_CONTROLLER if no rule was found otherwise. */
+ * - RULE_DPIF_LOOKUP_VERDICT_DEFAULT if no rule was found,
+ * 'honor_table_miss' is true and a table miss configuration has
+ * not been specified in this case. */
enum rule_dpif_lookup_verdict
rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto,
const struct flow *flow,
} else if (!honor_table_miss) {
return RULE_DPIF_LOOKUP_VERDICT_CONTROLLER;
} else {
- switch (table_get_config(&ofproto->up, *table_id)
- & OFPTC11_TABLE_MISS_MASK) {
- case OFPTC11_TABLE_MISS_CONTINUE:
+ switch (ofproto_table_get_config(&ofproto->up, *table_id)) {
+ case OFPROTO_TABLE_MISS_CONTINUE:
break;
- case OFPTC11_TABLE_MISS_CONTROLLER:
+ case OFPROTO_TABLE_MISS_CONTROLLER:
return RULE_DPIF_LOOKUP_VERDICT_CONTROLLER;
- case OFPTC11_TABLE_MISS_DROP:
+ case OFPROTO_TABLE_MISS_DROP:
return RULE_DPIF_LOOKUP_VERDICT_DROP;
+
+ case OFPROTO_TABLE_MISS_DEFAULT:
+ return RULE_DPIF_LOOKUP_VERDICT_DEFAULT;
}
}
}
ovs_mutex_lock(&ofproto->stats_mutex);
ofproto->stats.tx_packets++;
- ofproto->stats.tx_bytes += packet->size;
+ ofproto->stats.tx_bytes += ofpbuf_size(packet);
ovs_mutex_unlock(&ofproto->stats_mutex);
return error;
}
ds_put_char_multiple(result, '\t', level);
ds_put_format(result, "%s: ", title);
- format_odp_actions(result, odp_actions->data, odp_actions->size);
+ format_odp_actions(result, ofpbuf_data(odp_actions),
+ ofpbuf_size(odp_actions));
ds_put_char(result, '\n');
}
goto exit;
}
- if (xlate_receive(backer, NULL, odp_key.data, odp_key.size, flow,
+ if (xlate_receive(backer, NULL, ofpbuf_data(&odp_key),
+ ofpbuf_size(&odp_key), flow,
ofprotop, NULL, NULL, NULL, NULL)) {
error = "Invalid datapath flow";
goto exit;
/* Generate a packet, if requested. */
if (packet) {
- if (!packet->size) {
+ if (!ofpbuf_size(packet)) {
flow_compose(packet, flow);
} else {
- struct pkt_metadata md = PKT_METADATA_INITIALIZER_FLOW(flow);
+ struct pkt_metadata md = pkt_metadata_from_flow(flow);
/* Use the metadata from the flow and the packet argument
* to reconstruct the flow. */
goto exit;
}
if (enforce_consistency) {
- retval = ofpacts_check_consistency(ofpacts.data, ofpacts.size, &flow,
- u16_to_ofp(ofproto->up.max_ports),
+ retval = ofpacts_check_consistency(ofpbuf_data(&ofpacts), ofpbuf_size(&ofpacts),
+ &flow, u16_to_ofp(ofproto->up.max_ports),
0, 0, usable_protocols);
} else {
- retval = ofpacts_check(ofpacts.data, ofpacts.size, &flow,
+ retval = ofpacts_check(ofpbuf_data(&ofpacts), ofpbuf_size(&ofpacts), &flow,
u16_to_ofp(ofproto->up.max_ports), 0, 0,
&usable_protocols);
}
goto exit;
}
- ofproto_trace(ofproto, &flow, packet, ofpacts.data, ofpacts.size, &result);
+ ofproto_trace(ofproto, &flow, packet,
+ ofpbuf_data(&ofpacts), ofpbuf_size(&ofpacts), &result);
unixctl_command_reply(conn, ds_cstr(&result));
exit:
trace_format_megaflow(ds, 0, "Megaflow", &trace);
ds_put_cstr(ds, "Datapath actions: ");
- format_odp_actions(ds, trace.xout.odp_actions.data,
- trace.xout.odp_actions.size);
+ format_odp_actions(ds, ofpbuf_data(&trace.xout.odp_actions),
+ ofpbuf_size(&trace.xout.odp_actions));
if (trace.xout.slow) {
enum slow_path_reason slow;
return !hmap_is_empty(&ofproto->realdev_vid_map);
}
+
static ofp_port_t
vsp_realdev_to_vlandev__(const struct ofproto_dpif *ofproto,
ofp_port_t realdev_ofp_port, ovs_be16 vlan_tci)
}
}
+uint32_t
+ofproto_dpif_alloc_recirc_id(struct ofproto_dpif *ofproto)
+{
+ struct dpif_backer *backer = ofproto->backer;
+
+ return recirc_id_alloc(backer->rid_pool);
+}
+
+void
+ofproto_dpif_free_recirc_id(struct ofproto_dpif *ofproto, uint32_t recirc_id)
+{
+ struct dpif_backer *backer = ofproto->backer;
+
+ recirc_id_free(backer->rid_pool, recirc_id);
+}
+
const struct ofproto_class ofproto_dpif_class = {
init,
enumerate_types,