2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 06:15:47 +00:00

ofproto/bond: Implement bond megaflow using recirculation

Infrastructure to enable megaflow support for bond ports using
recirculation. This patch adds the following features:
* Generate RECIRC action when bond can benefit from recirculation.
* Populate post recirculation rules in a hidden table. Currently table 254.
* Uses post recirculation rules for bond rebalancing
* A recirculation implementation in dpif-netdev.

The goal of this patch is to be able to megaflow bond outputs and
thus greatly improve performance. However, this patch does not
actually improve the megaflow generation. It is left for a later commit.

Signed-off-by: Andy Zhou <azhou@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Andy Zhou
2014-03-05 15:27:31 -08:00
parent ebed9f7859
commit adcf00ba35
20 changed files with 910 additions and 143 deletions

View File

@@ -68,6 +68,9 @@ VLOG_DEFINE_THIS_MODULE(dpif_netdev);
#define NETDEV_RULE_PRIORITY 0x8000
#define NR_THREADS 1
/* Use per thread recirc_depth to prevent recirculation loop. */
#define MAX_RECIRC_DEPTH 5
DEFINE_STATIC_PER_THREAD_DATA(uint32_t, recirc_depth, 0)
/* Configuration parameters. */
enum { MAX_FLOWS = 65536 }; /* Maximum number of flows in flow table. */
@@ -1997,8 +2000,9 @@ dp_netdev_count_packet(struct dp_netdev *dp, enum dp_stat_type type)
}
static void
dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
struct pkt_metadata *md)
dp_netdev_input(struct dp_netdev *dp, struct ofpbuf *packet,
struct pkt_metadata *md)
OVS_REQ_RDLOCK(dp->port_rwlock)
{
struct dp_netdev_flow *netdev_flow;
struct flow key;
@@ -2027,6 +2031,17 @@ dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
}
}
static void
dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
struct pkt_metadata *md)
OVS_REQ_RDLOCK(dp->port_rwlock)
{
uint32_t *recirc_depth = recirc_depth_get();
*recirc_depth = 0;
dp_netdev_input(dp, packet, md);
}
static int
dp_netdev_output_userspace(struct dp_netdev *dp, struct ofpbuf *packet,
int queue_no, int type, const struct flow *flow,
@@ -2096,6 +2111,7 @@ dp_execute_cb(void *aux_, struct ofpbuf *packet,
struct dp_netdev_execute_aux *aux = aux_;
int type = nl_attr_type(a);
struct dp_netdev_port *p;
uint32_t *depth = recirc_depth_get();
switch ((enum ovs_action_attr)type) {
case OVS_ACTION_ATTR_OUTPUT:
@@ -2122,23 +2138,40 @@ dp_execute_cb(void *aux_, struct ofpbuf *packet,
break;
}
case OVS_ACTION_ATTR_RECIRC: {
const struct ovs_action_recirc *act;
case OVS_ACTION_ATTR_RECIRC:
if (*depth < MAX_RECIRC_DEPTH) {
uint32_t old_recirc_id = md->recirc_id;
uint32_t old_dp_hash = md->dp_hash;
const struct ovs_action_recirc *act;
struct ofpbuf *recirc_packet;
act = nl_attr_get(a);
md->recirc_id = act->recirc_id;
md->dp_hash = 0;
recirc_packet = may_steal ? packet : ofpbuf_clone(packet);
if (act->hash_alg == OVS_RECIRC_HASH_ALG_L4) {
struct flow flow;
act = nl_attr_get(a);
md->recirc_id = act->recirc_id;
md->dp_hash = 0;
flow_extract(packet, md, &flow);
md->dp_hash = flow_hash_symmetric_l4(&flow, act->hash_bias);
if (act->hash_alg == OVS_RECIRC_HASH_ALG_L4) {
struct flow flow;
flow_extract(recirc_packet, md, &flow);
md->dp_hash = flow_hash_symmetric_l4(&flow, act->hash_bias);
if (!md->dp_hash) {
md->dp_hash = 1; /* 0 is not valid */
}
}
(*depth)++;
dp_netdev_input(aux->dp, recirc_packet, md);
(*depth)--;
md->recirc_id = old_recirc_id;
md->recirc_id = old_dp_hash;
break;
} else {
VLOG_WARN("Packet dropped. Max recirculation depth exceeded.");
}
dp_netdev_port_input(aux->dp, packet, md);
break;
}
case OVS_ACTION_ATTR_PUSH_VLAN:
case OVS_ACTION_ATTR_POP_VLAN:
@@ -2150,7 +2183,6 @@ dp_execute_cb(void *aux_, struct ofpbuf *packet,
case __OVS_ACTION_ATTR_MAX:
OVS_NOT_REACHED();
}
}
static void