bool create, struct dpif **);
static int dp_netdev_output_userspace(struct dp_netdev *dp, struct ofpbuf *,
int queue_no, int type,
- const struct flow *,
+ const struct miniflow *,
const struct nlattr *userdata);
static void dp_netdev_execute_actions(struct dp_netdev *dp,
- const struct flow *, struct ofpbuf *, bool may_steal,
+ const struct miniflow *,
+ struct ofpbuf *, bool may_steal,
struct pkt_metadata *,
const struct nlattr *actions,
size_t actions_len);
}
static struct dp_netdev_flow *
-dp_netdev_lookup_flow(const struct dp_netdev *dp, const struct flow *flow)
+dp_netdev_lookup_flow(const struct dp_netdev *dp, const struct miniflow *key)
OVS_EXCLUDED(dp->cls.rwlock)
{
struct dp_netdev_flow *netdev_flow;
+ struct cls_rule *rule;
fat_rwlock_rdlock(&dp->cls.rwlock);
- netdev_flow = dp_netdev_flow_cast(classifier_lookup(&dp->cls, flow, NULL));
+ rule = classifier_lookup_miniflow_first(&dp->cls, key);
+ netdev_flow = dp_netdev_flow_cast(rule);
fat_rwlock_unlock(&dp->cls.rwlock);
return netdev_flow;
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_flow *netdev_flow;
struct flow flow;
+ struct miniflow miniflow;
struct flow_wildcards wc;
int error;
if (error) {
return error;
}
+ miniflow_init(&miniflow, &flow);
ovs_mutex_lock(&dp->flow_mutex);
- netdev_flow = dp_netdev_lookup_flow(dp, &flow);
+ netdev_flow = dp_netdev_lookup_flow(dp, &miniflow);
if (!netdev_flow) {
if (put->flags & DPIF_FP_CREATE) {
if (hmap_count(&dp->flow_table) < MAX_FLOWS) {
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct pkt_metadata *md = &execute->md;
- struct flow key;
+ struct miniflow key;
+ uint32_t buf[FLOW_U32S];
if (ofpbuf_size(execute->packet) < ETH_HEADER_LEN ||
ofpbuf_size(execute->packet) > UINT16_MAX) {
}
/* Extract flow key. */
- flow_extract(execute->packet, md, &key);
+ miniflow_initialize(&key, buf);
+ miniflow_extract(execute->packet, md, &key);
ovs_rwlock_rdlock(&dp->port_rwlock);
dp_netdev_execute_actions(dp, &key, execute->packet, false, md,
static void
dp_netdev_flow_used(struct dp_netdev_flow *netdev_flow,
const struct ofpbuf *packet,
- const struct flow *key)
+ const struct miniflow *key)
{
- uint16_t tcp_flags = ntohs(key->tcp_flags);
+ uint16_t tcp_flags = miniflow_get_tcp_flags(key);
long long int now = time_msec();
struct dp_netdev_flow_stats *bucket;
OVS_REQ_RDLOCK(dp->port_rwlock)
{
struct dp_netdev_flow *netdev_flow;
- struct flow key;
+ struct miniflow key;
+ uint32_t buf[FLOW_U32S];
if (ofpbuf_size(packet) < ETH_HEADER_LEN) {
ofpbuf_delete(packet);
return;
}
- flow_extract(packet, md, &key);
+ miniflow_initialize(&key, buf);
+ miniflow_extract(packet, md, &key);
+
netdev_flow = dp_netdev_lookup_flow(dp, &key);
if (netdev_flow) {
struct dp_netdev_actions *actions;
} else if (dp->handler_queues) {
dp_netdev_count_packet(dp, DP_STAT_MISS);
dp_netdev_output_userspace(dp, packet,
- flow_hash_5tuple(&key, 0) % dp->n_handlers,
+ miniflow_hash_5tuple(&key, 0)
+ % dp->n_handlers,
DPIF_UC_MISS, &key, NULL);
ofpbuf_delete(packet);
}
static int
dp_netdev_output_userspace(struct dp_netdev *dp, struct ofpbuf *packet,
- int queue_no, int type, const struct flow *flow,
+ int queue_no, int type, const struct miniflow *key,
const struct nlattr *userdata)
{
struct dp_netdev_queue *q;
struct dpif_upcall *upcall = &u->upcall;
struct ofpbuf *buf = &u->buf;
size_t buf_size;
+ struct flow flow;
upcall->type = type;
ofpbuf_init(buf, buf_size);
/* Put ODP flow. */
- odp_flow_key_from_flow(buf, flow, flow->in_port.odp_port);
+ miniflow_expand(key, &flow);
+ odp_flow_key_from_flow(buf, &flow, flow.in_port.odp_port);
upcall->key = ofpbuf_data(buf);
upcall->key_len = ofpbuf_size(buf);
struct dp_netdev_execute_aux {
struct dp_netdev *dp;
- const struct flow *key;
+ const struct miniflow *key;
};
static void
userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
dp_netdev_output_userspace(aux->dp, packet,
- flow_hash_5tuple(aux->key, 0)
+ miniflow_hash_5tuple(aux->key, 0)
% aux->dp->n_handlers,
DPIF_UC_ACTION, aux->key,
userdata);
hash_act = nl_attr_get(a);
if (hash_act->hash_alg == OVS_HASH_ALG_L4) {
-
- hash = flow_hash_symmetric_l4(aux->key, hash_act->hash_bias);
+ /* Hash need not be symmetric, nor does it need to include
+ * L2 fields. */
+ hash = miniflow_hash_5tuple(aux->key, hash_act->hash_bias);
if (!hash) {
hash = 1; /* 0 is not valid */
}
}
static void
-dp_netdev_execute_actions(struct dp_netdev *dp, const struct flow *key,
+dp_netdev_execute_actions(struct dp_netdev *dp, const struct miniflow *key,
struct ofpbuf *packet, bool may_steal,
struct pkt_metadata *md,
const struct nlattr *actions, size_t actions_len)