lib/ovsdb-parser.h \
lib/ovsdb-types.c \
lib/ovsdb-types.h \
+ lib/packet-dpif.c \
+ lib/packet-dpif.h \
lib/packets.c \
lib/packets.h \
lib/pcap-file.c \
#include "ofp-print.h"
#include "ofpbuf.h"
#include "ovs-rcu.h"
+#include "packet-dpif.h"
#include "packets.h"
#include "poll-loop.h"
#include "random.h"
const struct nlattr *userdata);
static void dp_netdev_execute_actions(struct dp_netdev *dp,
const struct miniflow *,
- struct ofpbuf *, bool may_steal,
+ struct dpif_packet *, bool may_steal,
struct pkt_metadata *,
const struct nlattr *actions,
size_t actions_len);
-static void dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
+static void dp_netdev_port_input(struct dp_netdev *dp,
+ struct dpif_packet *packet,
struct pkt_metadata *);
static void dp_netdev_set_pmd_threads(struct dp_netdev *, int n);
dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
+ struct dpif_packet packet;
struct pkt_metadata *md = &execute->md;
struct {
struct miniflow flow;
miniflow_initialize(&key.flow, key.buf);
miniflow_extract(execute->packet, md, &key.flow);
- dp_netdev_execute_actions(dp, &key.flow, execute->packet, false, md,
+ packet.ofpbuf = *execute->packet;
+
+ dp_netdev_execute_actions(dp, &key.flow, &packet, false, md,
execute->actions, execute->actions_len);
+ /* Even though may_steal is set to false, some actions could modify or
+ * reallocate the ofpbuf memory. We need to pass those changes to the
+ * caller */
+ *execute->packet = packet.ofpbuf;
+
return 0;
}
struct dp_netdev_port *port,
struct netdev_rxq *rxq)
{
- struct ofpbuf *packet[NETDEV_MAX_RX_BATCH];
+ struct dpif_packet *packet[NETDEV_MAX_RX_BATCH];
int error, c;
error = netdev_rxq_recv(rxq, packet, &c);
}
static void
-dp_netdev_input(struct dp_netdev *dp, struct ofpbuf *packet,
+dp_netdev_input(struct dp_netdev *dp, struct dpif_packet *packet,
struct pkt_metadata *md)
{
struct dp_netdev_flow *netdev_flow;
+ struct ofpbuf *buf = &packet->ofpbuf;
struct {
struct miniflow flow;
uint32_t buf[FLOW_U32S];
} key;
- if (ofpbuf_size(packet) < ETH_HEADER_LEN) {
- ofpbuf_delete(packet);
+ if (ofpbuf_size(buf) < ETH_HEADER_LEN) {
+ dpif_packet_delete(packet);
return;
}
miniflow_initialize(&key.flow, key.buf);
- miniflow_extract(packet, md, &key.flow);
+ miniflow_extract(buf, md, &key.flow);
netdev_flow = dp_netdev_lookup_flow(dp, &key.flow);
if (netdev_flow) {
struct dp_netdev_actions *actions;
- dp_netdev_flow_used(netdev_flow, packet, &key.flow);
+ dp_netdev_flow_used(netdev_flow, buf, &key.flow);
actions = dp_netdev_flow_get_actions(netdev_flow);
dp_netdev_execute_actions(dp, &key.flow, packet, true, md,
dp_netdev_count_packet(dp, DP_STAT_HIT);
} else if (dp->handler_queues) {
dp_netdev_count_packet(dp, DP_STAT_MISS);
- dp_netdev_output_userspace(dp, packet,
- miniflow_hash_5tuple(&key.flow, 0)
+ dp_netdev_output_userspace(dp, buf, miniflow_hash_5tuple(&key.flow, 0)
% dp->n_handlers,
DPIF_UC_MISS, &key.flow, NULL);
}
}
static void
-dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
+dp_netdev_port_input(struct dp_netdev *dp, struct dpif_packet *packet,
struct pkt_metadata *md)
{
uint32_t *recirc_depth = recirc_depth_get();
};
static void
-dp_execute_cb(void *aux_, struct ofpbuf *packet,
+dp_execute_cb(void *aux_, struct dpif_packet *packet,
struct pkt_metadata *md,
const struct nlattr *a, bool may_steal)
OVS_NO_THREAD_SAFETY_ANALYSIS
const struct nlattr *userdata;
userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
- userspace_packet = may_steal ? packet : ofpbuf_clone(packet);
+ userspace_packet = may_steal
+ ? &packet->ofpbuf
+ : ofpbuf_clone(&packet->ofpbuf);
dp_netdev_output_userspace(aux->dp, userspace_packet,
miniflow_hash_5tuple(aux->key, 0)
case OVS_ACTION_ATTR_RECIRC:
if (*depth < MAX_RECIRC_DEPTH) {
struct pkt_metadata recirc_md = *md;
- struct ofpbuf *recirc_packet;
+ struct dpif_packet *recirc_packet;
- recirc_packet = may_steal ? packet : ofpbuf_clone(packet);
+ recirc_packet = may_steal ? packet : dpif_packet_clone(packet);
recirc_md.recirc_id = nl_attr_get_u32(a);
(*depth)++;
static void
dp_netdev_execute_actions(struct dp_netdev *dp, const struct miniflow *key,
- struct ofpbuf *packet, bool may_steal,
+ struct dpif_packet *packet, bool may_steal,
struct pkt_metadata *md,
const struct nlattr *actions, size_t actions_len)
{
#include "ofp-print.h"
#include "ofp-util.h"
#include "ofpbuf.h"
+#include "packet-dpif.h"
#include "packets.h"
#include "poll-loop.h"
#include "shash.h"
/* This is called for actions that need the context of the datapath to be
* meaningful. */
static void
-dpif_execute_helper_cb(void *aux_, struct ofpbuf *packet,
+dpif_execute_helper_cb(void *aux_, struct dpif_packet *packet,
struct pkt_metadata *md,
const struct nlattr *action, bool may_steal OVS_UNUSED)
{
case OVS_ACTION_ATTR_RECIRC:
execute.actions = action;
execute.actions_len = NLA_ALIGN(action->nla_len);
- execute.packet = packet;
+ execute.packet = &packet->ofpbuf;
execute.md = *md;
execute.needs_help = false;
aux->error = aux->dpif->dpif_class->execute(aux->dpif, &execute);
dpif_execute_with_help(struct dpif *dpif, struct dpif_execute *execute)
{
struct dpif_execute_helper_aux aux = {dpif, 0};
+ struct dpif_packet packet;
COVERAGE_INC(dpif_execute_with_help);
- odp_execute_actions(&aux, execute->packet, false, &execute->md,
- execute->actions, execute->actions_len,
- dpif_execute_helper_cb);
+ packet.ofpbuf = *execute->packet;
+
+ odp_execute_actions(&aux, &packet, false, &execute->md, execute->actions,
+ execute->actions_len, dpif_execute_helper_cb);
+
+ /* Even though may_steal is set to false, some actions could modify or
+ * reallocate the ofpbuf memory. We need to pass those changes to the
+ * caller */
+ *execute->packet = packet.ofpbuf;
+
return aux.error;
}
#include "ofpbuf.h"
#include "openflow/openflow.h"
#include "ovs-thread.h"
+#include "packet-dpif.h"
#include "packets.h"
#include "poll-loop.h"
#include "shash.h"
}
static int
-netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct ofpbuf **packet, int *c)
+netdev_bsd_rxq_recv(struct netdev_rxq *rxq_, struct dpif_packet **packets,
+ int *c)
{
struct netdev_rxq_bsd *rxq = netdev_rxq_bsd_cast(rxq_);
struct netdev *netdev = rxq->up.netdev;
+ struct dpif_packet *packet;
struct ofpbuf *buffer;
ssize_t retval;
int mtu;
mtu = ETH_PAYLOAD_MAX;
}
- buffer = ofpbuf_new_with_headroom(VLAN_ETH_HEADER_LEN + mtu, DP_NETDEV_HEADROOM);
+ packet = dpif_packet_new_with_headroom(VLAN_ETH_HEADER_LEN + mtu,
+ DP_NETDEV_HEADROOM);
+ buffer = &packet->ofpbuf;
retval = (rxq->pcap_handle
? netdev_rxq_bsd_recv_pcap(rxq, buffer)
: netdev_rxq_bsd_recv_tap(rxq, buffer));
if (retval) {
- ofpbuf_delete(buffer);
+ dpif_packet_delete(packet);
} else {
dp_packet_pad(buffer);
- packet[0] = buffer;
+ packets[0] = packet;
*c = 1;
}
return retval;
* system or a tap device.
*/
static int
-netdev_bsd_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal)
+netdev_bsd_send(struct netdev *netdev_, struct dpif_packet *pkt,
+ bool may_steal)
{
struct netdev_bsd *dev = netdev_bsd_cast(netdev_);
const char *name = netdev_get_name(netdev_);
- const void *data = ofpbuf_data(pkt);
- size_t size = ofpbuf_size(pkt);
+ const void *data = ofpbuf_data(&pkt->ofpbuf);
+ size_t size = ofpbuf_size(&pkt->ofpbuf);
int error;
ovs_mutex_lock(&dev->mutex);
ovs_mutex_unlock(&dev->mutex);
if (may_steal) {
- ofpbuf_delete(pkt);
+ dpif_packet_delete(pkt);
}
return error;
#include "ofpbuf.h"
#include "ovs-thread.h"
#include "ovs-rcu.h"
+#include "packet-dpif.h"
#include "packets.h"
#include "shash.h"
#include "sset.h"
}
void
-free_dpdk_buf(struct ofpbuf *b)
+free_dpdk_buf(struct dpif_packet *p)
{
+ struct ofpbuf *b = &p->ofpbuf;
struct rte_mbuf *pkt = (struct rte_mbuf *) b->dpdk_buf;
rte_mempool_put(pkt->pool, pkt);
unsigned i OVS_UNUSED)
{
struct rte_mbuf *m = _m;
- uint32_t buf_len = mp->elt_size - sizeof(struct ofpbuf);
+ uint32_t buf_len = mp->elt_size - sizeof(struct dpif_packet);
- RTE_MBUF_ASSERT(mp->elt_size >= sizeof(struct ofpbuf));
+ RTE_MBUF_ASSERT(mp->elt_size >= sizeof(struct dpif_packet));
memset(m, 0, mp->elt_size);
/* start of buffer is just after mbuf structure */
- m->buf_addr = (char *)m + sizeof(struct ofpbuf);
+ m->buf_addr = (char *)m + sizeof(struct dpif_packet);
m->buf_physaddr = rte_mempool_virt2phy(mp, m) +
- sizeof(struct ofpbuf);
+ sizeof(struct dpif_packet);
m->buf_len = (uint16_t)buf_len;
/* keep some headroom between start of buffer and data */
}
static int
-netdev_dpdk_rxq_recv(struct netdev_rxq *rxq_, struct ofpbuf **packets, int *c)
+netdev_dpdk_rxq_recv(struct netdev_rxq *rxq_, struct dpif_packet **packets,
+ int *c)
{
struct netdev_rxq_dpdk *rx = netdev_rxq_dpdk_cast(rxq_);
struct netdev *netdev = rx->up.netdev;
static int
netdev_dpdk_send(struct netdev *netdev,
- struct ofpbuf *ofpbuf, bool may_steal)
+ struct dpif_packet *packet, bool may_steal)
{
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+ struct ofpbuf *ofpbuf = &packet->ofpbuf;
int ret;
if (ofpbuf_size(ofpbuf) > dev->max_packet_len) {
dpdk_do_tx_copy(netdev, (char *) ofpbuf_data(ofpbuf), ofpbuf_size(ofpbuf));
if (may_steal) {
- ofpbuf_delete(ofpbuf);
+ dpif_packet_delete(packet);
}
} else {
int qid;
#include <config.h>
#include "ofpbuf.h"
+struct dpif_packet;
+
#ifdef DPDK_NETDEV
#include <rte_config.h>
int dpdk_init(int argc, char **argv);
void netdev_dpdk_register(void);
-void free_dpdk_buf(struct ofpbuf *);
+void free_dpdk_buf(struct dpif_packet *);
int pmd_thread_setaffinity_cpu(int cpu);
#else
}
static inline void
-free_dpdk_buf(struct ofpbuf *buf OVS_UNUSED)
+free_dpdk_buf(struct dpif_packet *buf OVS_UNUSED)
{
/* Nothing */
}
#include "odp-util.h"
#include "ofp-print.h"
#include "ofpbuf.h"
+#include "packet-dpif.h"
#include "packets.h"
#include "pcap-file.h"
#include "poll-loop.h"
}
static int
-netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct ofpbuf **arr, int *c)
+netdev_dummy_rxq_recv(struct netdev_rxq *rxq_, struct dpif_packet **arr,
+ int *c)
{
struct netdev_rxq_dummy *rx = netdev_rxq_dummy_cast(rxq_);
struct netdev_dummy *netdev = netdev_dummy_cast(rx->up.netdev);
ovs_mutex_unlock(&netdev->mutex);
dp_packet_pad(packet);
- arr[0] = packet;
+
+ /* This performs a (sometimes unnecessary) copy */
+ arr[0] = dpif_packet_clone_from_ofpbuf(packet);
+ ofpbuf_delete(packet);
*c = 1;
return 0;
}
}
static int
-netdev_dummy_send(struct netdev *netdev, struct ofpbuf *pkt, bool may_steal)
+netdev_dummy_send(struct netdev *netdev, struct dpif_packet *pkt,
+ bool may_steal)
{
struct netdev_dummy *dev = netdev_dummy_cast(netdev);
- const void *buffer = ofpbuf_data(pkt);
- size_t size = ofpbuf_size(pkt);
+ const void *buffer = ofpbuf_data(&pkt->ofpbuf);
+ size_t size = ofpbuf_size(&pkt->ofpbuf);
if (size < ETH_HEADER_LEN) {
return EMSGSIZE;
ovs_mutex_unlock(&dev->mutex);
if (may_steal) {
- ofpbuf_delete(pkt);
+ dpif_packet_delete(pkt);
}
return 0;
#include "ofpbuf.h"
#include "openflow/openflow.h"
#include "ovs-atomic.h"
+#include "packet-dpif.h"
#include "packets.h"
#include "poll-loop.h"
#include "rtnetlink-link.h"
}
static int
-netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct ofpbuf **packet, int *c)
+netdev_linux_rxq_recv(struct netdev_rxq *rxq_, struct dpif_packet **packets,
+ int *c)
{
struct netdev_rxq_linux *rx = netdev_rxq_linux_cast(rxq_);
struct netdev *netdev = rx->up.netdev;
+ struct dpif_packet *packet;
struct ofpbuf *buffer;
ssize_t retval;
int mtu;
mtu = ETH_PAYLOAD_MAX;
}
- buffer = ofpbuf_new_with_headroom(VLAN_ETH_HEADER_LEN + mtu, DP_NETDEV_HEADROOM);
+ packet = dpif_packet_new_with_headroom(VLAN_ETH_HEADER_LEN + mtu,
+ DP_NETDEV_HEADROOM);
+ buffer = &packet->ofpbuf;
retval = (rx->is_tap
? netdev_linux_rxq_recv_tap(rx->fd, buffer)
ofpbuf_delete(buffer);
} else {
dp_packet_pad(buffer);
- packet[0] = buffer;
+ packets[0] = packet;
*c = 1;
}
* The kernel maintains a packet transmission queue, so the caller is not
* expected to do additional queuing of packets. */
static int
-netdev_linux_send(struct netdev *netdev_, struct ofpbuf *pkt, bool may_steal)
+netdev_linux_send(struct netdev *netdev_, struct dpif_packet *pkt,
+ bool may_steal)
{
- const void *data = ofpbuf_data(pkt);
- size_t size = ofpbuf_size(pkt);
+ const void *data = ofpbuf_data(&pkt->ofpbuf);
+ size_t size = ofpbuf_size(&pkt->ofpbuf);
for (;;) {
ssize_t retval;
}
if (may_steal) {
- ofpbuf_delete(pkt);
+ dpif_packet_delete(pkt);
}
if (retval < 0) {
* network device from being usefully used by the netdev-based "userspace
* datapath". It will also prevent the OVS implementation of bonding from
* working properly over 'netdev'.) */
- int (*send)(struct netdev *netdev, struct ofpbuf *buffer, bool may_steal);
+ int (*send)(struct netdev *netdev, struct dpif_packet *buffer,
+ bool may_steal);
/* Registers with the poll loop to wake up from the next call to
* poll_block() when the packet transmission queue for 'netdev' has
void (*rxq_destruct)(struct netdev_rxq *);
void (*rxq_dealloc)(struct netdev_rxq *);
- /* Attempts to receive batch of packets from 'rx' and place array of pointers
- * into '*pkt'. netdev is responsible for allocating buffers.
+ /* Attempts to receive batch of packets from 'rx' and place array of
+ * pointers into '*pkts'. netdev is responsible for allocating buffers.
* '*cnt' points to packet count for given batch. Once packets are returned
* to caller, netdev should give up ownership of ofpbuf data.
*
* Caller is expected to pass array of size MAX_RX_BATCH.
* This function may be set to null if it would always return EOPNOTSUPP
* anyhow. */
- int (*rxq_recv)(struct netdev_rxq *rx, struct ofpbuf **pkt, int *cnt);
+ int (*rxq_recv)(struct netdev_rxq *rx, struct dpif_packet **pkts,
+ int *cnt);
/* Registers with the poll loop to wake up from the next call to
* poll_block() when a packet is ready to be received with netdev_rxq_recv()
* This function may be set to null if it would always return EOPNOTSUPP
* anyhow. */
int
-netdev_rxq_recv(struct netdev_rxq *rx, struct ofpbuf **buffers, int *cnt)
+netdev_rxq_recv(struct netdev_rxq *rx, struct dpif_packet **buffers, int *cnt)
{
int retval;
* Some network devices may not implement support for this function. In such
* cases this function will always return EOPNOTSUPP. */
int
-netdev_send(struct netdev *netdev, struct ofpbuf *buffer, bool may_steal)
+netdev_send(struct netdev *netdev, struct dpif_packet *buffer, bool may_steal)
{
int error;
* netdev and access each of those from a different thread.)
*/
+struct dpif_packet;
struct netdev;
struct netdev_class;
struct netdev_rxq;
const char *netdev_rxq_get_name(const struct netdev_rxq *);
-int netdev_rxq_recv(struct netdev_rxq *rx, struct ofpbuf **buffers, int *cnt);
+int netdev_rxq_recv(struct netdev_rxq *rx, struct dpif_packet **buffers,
+ int *cnt);
void netdev_rxq_wait(struct netdev_rxq *);
int netdev_rxq_drain(struct netdev_rxq *);
/* Packet transmission. */
-int netdev_send(struct netdev *, struct ofpbuf *, bool may_steal);
+int netdev_send(struct netdev *, struct dpif_packet *, bool may_steal);
void netdev_send_wait(struct netdev *);
/* Hardware address. */
#include "netlink.h"
#include "ofpbuf.h"
#include "odp-util.h"
+#include "packet-dpif.h"
#include "packets.h"
#include "flow.h"
#include "unaligned.h"
}
static void
-odp_execute_set_action(struct ofpbuf *packet, const struct nlattr *a,
+odp_execute_set_action(struct dpif_packet *packet, const struct nlattr *a,
struct pkt_metadata *md)
{
enum ovs_key_attr type = nl_attr_type(a);
break;
case OVS_KEY_ATTR_ETHERNET:
- odp_eth_set_addrs(packet,
+ odp_eth_set_addrs(&packet->ofpbuf,
nl_attr_get_unspec(a, sizeof(struct ovs_key_ethernet)));
break;
case OVS_KEY_ATTR_IPV4:
ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4));
- packet_set_ipv4(packet, ipv4_key->ipv4_src, ipv4_key->ipv4_dst,
- ipv4_key->ipv4_tos, ipv4_key->ipv4_ttl);
+ packet_set_ipv4(&packet->ofpbuf, ipv4_key->ipv4_src,
+ ipv4_key->ipv4_dst, ipv4_key->ipv4_tos,
+ ipv4_key->ipv4_ttl);
break;
case OVS_KEY_ATTR_IPV6:
ipv6_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv6));
- packet_set_ipv6(packet, ipv6_key->ipv6_proto, ipv6_key->ipv6_src,
- ipv6_key->ipv6_dst, ipv6_key->ipv6_tclass,
- ipv6_key->ipv6_label, ipv6_key->ipv6_hlimit);
+ packet_set_ipv6(&packet->ofpbuf, ipv6_key->ipv6_proto,
+ ipv6_key->ipv6_src, ipv6_key->ipv6_dst,
+ ipv6_key->ipv6_tclass, ipv6_key->ipv6_label,
+ ipv6_key->ipv6_hlimit);
break;
case OVS_KEY_ATTR_TCP:
tcp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp));
- packet_set_tcp_port(packet, tcp_key->tcp_src, tcp_key->tcp_dst);
+ packet_set_tcp_port(&packet->ofpbuf, tcp_key->tcp_src,
+ tcp_key->tcp_dst);
break;
case OVS_KEY_ATTR_UDP:
udp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_udp));
- packet_set_udp_port(packet, udp_key->udp_src, udp_key->udp_dst);
+ packet_set_udp_port(&packet->ofpbuf, udp_key->udp_src,
+ udp_key->udp_dst);
break;
case OVS_KEY_ATTR_SCTP:
sctp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_sctp));
- packet_set_sctp_port(packet, sctp_key->sctp_src, sctp_key->sctp_dst);
+ packet_set_sctp_port(&packet->ofpbuf, sctp_key->sctp_src,
+ sctp_key->sctp_dst);
break;
case OVS_KEY_ATTR_MPLS:
- set_mpls_lse(packet, nl_attr_get_be32(a));
+ set_mpls_lse(&packet->ofpbuf, nl_attr_get_be32(a));
break;
case OVS_KEY_ATTR_ARP:
- set_arp(packet, nl_attr_get_unspec(a, sizeof(struct ovs_key_arp)));
+ set_arp(&packet->ofpbuf,
+ nl_attr_get_unspec(a, sizeof(struct ovs_key_arp)));
break;
case OVS_KEY_ATTR_DP_HASH:
}
static void
-odp_execute_actions__(void *dp, struct ofpbuf *packet, bool steal,
+odp_execute_actions__(void *dp, struct dpif_packet *packet, bool steal,
struct pkt_metadata *,
const struct nlattr *actions, size_t actions_len,
odp_execute_cb dp_execute_action, bool more_actions);
static void
-odp_execute_sample(void *dp, struct ofpbuf *packet, bool steal,
+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)
{
}
static void
-odp_execute_actions__(void *dp, struct ofpbuf *packet, bool steal,
+odp_execute_actions__(void *dp, struct dpif_packet *packet, bool steal,
struct pkt_metadata *md,
const struct nlattr *actions, size_t actions_len,
odp_execute_cb dp_execute_action, bool more_actions)
struct flow flow;
uint32_t hash;
- flow_extract(packet, md, &flow);
+ flow_extract(&packet->ofpbuf, md, &flow);
hash = flow_hash_5tuple(&flow, hash_act->hash_basis);
md->dp_hash = hash ? hash : 1;
} else {
case OVS_ACTION_ATTR_PUSH_VLAN: {
const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
- eth_push_vlan(packet, htons(ETH_TYPE_VLAN), vlan->vlan_tci);
+ eth_push_vlan(&packet->ofpbuf,
+ htons(ETH_TYPE_VLAN), vlan->vlan_tci);
break;
}
case OVS_ACTION_ATTR_POP_VLAN:
- eth_pop_vlan(packet);
+ eth_pop_vlan(&packet->ofpbuf);
break;
case OVS_ACTION_ATTR_PUSH_MPLS: {
const struct ovs_action_push_mpls *mpls = nl_attr_get(a);
- push_mpls(packet, mpls->mpls_ethertype, mpls->mpls_lse);
+ push_mpls(&packet->ofpbuf,
+ mpls->mpls_ethertype, mpls->mpls_lse);
break;
}
case OVS_ACTION_ATTR_POP_MPLS:
- pop_mpls(packet, nl_attr_get_be16(a));
+ pop_mpls(&packet->ofpbuf, nl_attr_get_be16(a));
break;
case OVS_ACTION_ATTR_SET:
}
void
-odp_execute_actions(void *dp, struct ofpbuf *packet, bool steal,
+odp_execute_actions(void *dp, struct dpif_packet *packet, bool steal,
struct pkt_metadata *md,
const struct nlattr *actions, size_t actions_len,
odp_execute_cb dp_execute_action)
if (!actions_len && steal) {
/* Drop action. */
- ofpbuf_delete(packet);
+ dpif_packet_delete(packet);
}
}
#include "openvswitch/types.h"
struct nlattr;
-struct ofpbuf;
+struct dpif_packet;
struct pkt_metadata;
-typedef void (*odp_execute_cb)(void *dp, struct ofpbuf *packet,
+typedef void (*odp_execute_cb)(void *dp, struct dpif_packet *packet,
struct pkt_metadata *,
const struct nlattr *action, bool may_steal);
* to 'dp_execute_action', if non-NULL. Currently this is called only for
* actions OVS_ACTION_ATTR_OUTPUT and OVS_ACTION_ATTR_USERSPACE so
* 'dp_execute_action' needs to handle only these. */
-void odp_execute_actions(void *dp, struct ofpbuf *packet, bool steal,
- struct pkt_metadata *,
- const struct nlattr *actions, size_t actions_len,
- odp_execute_cb dp_execute_action);
+void odp_execute_actions(void *dp, struct dpif_packet *packet, bool steal,
+ struct pkt_metadata *,
+ const struct nlattr *actions, size_t actions_len,
+ odp_execute_cb dp_execute_action);
#endif
} else if (b->source == OFPBUF_DPDK) {
#ifdef DPDK_NETDEV
ovs_assert(b != b->dpdk_buf);
- free_dpdk_buf(b);
+ /* If this ofpbuf was allocated by DPDK it must have been
+ * created as a dpif_packet */
+ free_dpdk_buf((struct dpif_packet*) b);
#else
ovs_assert(b->source != OFPBUF_DPDK);
#endif
{
if (b) {
if (b->source == OFPBUF_DPDK) {
- free_dpdk_buf(b);
+ /* If this ofpbuf was allocated by DPDK it must have been
+ * created as a dpif_packet */
+ free_dpdk_buf((struct dpif_packet*) b);
return;
}
--- /dev/null
+/*
+ * Copyright (c) 2014 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+#include "packet-dpif.h"
+
+#include "ofpbuf.h"
+
+struct dpif_packet *
+dpif_packet_new_with_headroom(size_t size, size_t headroom)
+{
+ struct dpif_packet *p = xmalloc(sizeof *p);
+ struct ofpbuf *b = &p->ofpbuf;
+
+ ofpbuf_init(b, size + headroom);
+ ofpbuf_reserve(b, headroom);
+
+ return p;
+}
+
+struct dpif_packet *
+dpif_packet_clone_from_ofpbuf(const struct ofpbuf *b)
+{
+ struct dpif_packet *p = xmalloc(sizeof *p);
+ size_t headroom = ofpbuf_headroom(b);
+
+ ofpbuf_init(&p->ofpbuf, ofpbuf_size(b) + headroom);
+ ofpbuf_reserve(&p->ofpbuf, headroom);
+
+ ofpbuf_put(&p->ofpbuf, ofpbuf_data(b), ofpbuf_size(b));
+
+ if (b->frame) {
+ uintptr_t data_delta
+ = (char *)ofpbuf_data(&p->ofpbuf) - (char *)ofpbuf_data(b);
+
+ p->ofpbuf.frame = (char *) b->frame + data_delta;
+ }
+ p->ofpbuf.l2_5_ofs = b->l2_5_ofs;
+ p->ofpbuf.l3_ofs = b->l3_ofs;
+ p->ofpbuf.l4_ofs = b->l4_ofs;
+
+ return p;
+}
+
+struct dpif_packet *
+dpif_packet_clone(struct dpif_packet *p)
+{
+ struct dpif_packet *newp;
+
+ newp = dpif_packet_clone_from_ofpbuf(&p->ofpbuf);
+
+ return newp;
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PACKET_DPIF_H
+#define PACKET_DPIF_H 1
+
+#include "ofpbuf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* A packet received from a netdev and passed to a dpif. */
+
+struct dpif_packet {
+ struct ofpbuf ofpbuf; /* Packet data. */
+};
+
+struct dpif_packet *dpif_packet_new_with_headroom(size_t size,
+ size_t headroom);
+
+struct dpif_packet *dpif_packet_clone_from_ofpbuf(const struct ofpbuf *b);
+
+struct dpif_packet *dpif_packet_clone(struct dpif_packet *p);
+
+static inline void dpif_packet_delete(struct dpif_packet *p)
+{
+ struct ofpbuf *ofp = &p->ofpbuf;
+
+ ofpbuf_delete(ofp);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* packet-dpif.h */
#include "ofproto/ofproto-dpif-sflow.h"
#include "ofproto/ofproto-dpif.h"
#include "ofproto/ofproto-provider.h"
+#include "packet-dpif.h"
#include "tunnel.h"
#include "vlog.h"
uint16_t controller_id)
{
struct ofproto_packet_in *pin;
- struct ofpbuf *packet;
+ struct dpif_packet *packet;
struct pkt_metadata md = PKT_METADATA_INITIALIZER(0);
ctx->xout->slow |= SLOW_CONTROLLER;
return;
}
- packet = ofpbuf_clone(ctx->xin->packet);
+ packet = dpif_packet_clone_from_ofpbuf(ctx->xin->packet);
ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow,
&ctx->xout->odp_actions,
ofpbuf_size(&ctx->xout->odp_actions), NULL);
pin = xmalloc(sizeof *pin);
- pin->up.packet_len = ofpbuf_size(packet);
- pin->up.packet = ofpbuf_steal_data(packet);
+ pin->up.packet_len = ofpbuf_size(&packet->ofpbuf);
+ pin->up.packet = ofpbuf_steal_data(&packet->ofpbuf);
pin->up.reason = reason;
pin->up.table_id = ctx->table_id;
pin->up.cookie = (ctx->rule
}
}
ofproto_dpif_send_packet_in(ctx->xbridge->ofproto, pin);
- ofpbuf_delete(packet);
+ dpif_packet_delete(packet);
}
static void