miniflow_hash_5tuple(&key.flow, 0)
% dp->n_handlers,
DPIF_UC_MISS, &key.flow, NULL);
- ofpbuf_delete(packet);
}
}
if (userdata) {
buf_size += NLA_ALIGN(userdata->nla_len);
}
- buf_size += ofpbuf_size(packet);
ofpbuf_init(buf, buf_size);
/* Put ODP flow. */
NLA_ALIGN(userdata->nla_len));
}
- ofpbuf_set_data(&upcall->packet,
- ofpbuf_put(buf, ofpbuf_data(packet), ofpbuf_size(packet)));
- ofpbuf_set_size(&upcall->packet, ofpbuf_size(packet));
+ upcall->packet = *packet;
seq_change(q->seq);
error = 0;
} else {
dp_netdev_count_packet(dp, DP_STAT_LOST);
+ ofpbuf_delete(packet);
error = ENOBUFS;
}
ovs_mutex_unlock(&q->mutex);
break;
case OVS_ACTION_ATTR_USERSPACE: {
+ struct ofpbuf *userspace_packet;
const struct nlattr *userdata;
userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
+ userspace_packet = may_steal ? packet : ofpbuf_clone(packet);
- dp_netdev_output_userspace(aux->dp, packet,
+ dp_netdev_output_userspace(aux->dp, userspace_packet,
miniflow_hash_5tuple(aux->key, 0)
% aux->dp->n_handlers,
DPIF_UC_ACTION, aux->key,
userdata);
-
- if (may_steal) {
- ofpbuf_delete(packet);
- }
break;
}
ofpbuf_init_dpdk(struct ofpbuf *b, size_t allocated)
{
ofpbuf_init__(b, allocated, OFPBUF_DPDK);
+#ifdef DPDK_NETDEV
+ b->dpdk_buf = b;
+#endif
}
/* Initializes 'b' as an empty ofpbuf with an initial capacity of 'size'
if (b) {
if (b->source == OFPBUF_MALLOC) {
free(ofpbuf_base(b));
+ } else if (b->source == OFPBUF_DPDK) {
+#ifdef DPDK_NETDEV
+ ovs_assert(b != b->dpdk_buf);
+ free_dpdk_buf(b);
+#else
+ ovs_assert(b->source != OFPBUF_DPDK);
+#endif
}
- ovs_assert(b->source != OFPBUF_DPDK);
}
}
struct ofpbuf {
#ifdef DPDK_NETDEV
struct rte_mbuf mbuf; /* DPDK mbuf */
+ void *dpdk_buf; /* First byte of allocated DPDK buffer. */
#else
void *base_; /* First byte of allocated space. */
void *data_; /* First byte actually in use. */
}
#ifdef DPDK_NETDEV
+BUILD_ASSERT_DECL(offsetof(struct ofpbuf, mbuf) == 0);
+
static inline void * ofpbuf_data(const struct ofpbuf *b)
{
return b->mbuf.pkt.data;