#include "coverage.h"
#include "dpif.h"
+#include "dp-packet.h"
#include "dynamic-string.h"
#include "fatal-signal.h"
#include "hash.h"
#include "netdev-dpdk.h"
#include "netdev-provider.h"
#include "netdev-vport.h"
-#include "ofpbuf.h"
+#include "odp-netlink.h"
#include "openflow/openflow.h"
#include "packets.h"
#include "poll-loop.h"
#include "sset.h"
#include "svec.h"
#include "openvswitch/vlog.h"
+#include "flow.h"
VLOG_DEFINE_THIS_MODULE(netdev);
netdev_is_pmd(const struct netdev *netdev)
{
return (!strcmp(netdev->netdev_class->type, "dpdk") ||
- !strcmp(netdev->netdev_class->type, "dpdkr"));
+ !strcmp(netdev->netdev_class->type, "dpdkr") ||
+ !strcmp(netdev->netdev_class->type, "dpdkvhostcuse") ||
+ !strcmp(netdev->netdev_class->type, "dpdkvhostuser"));
}
static void
struct netdev_registered_class *rc;
int error;
+ netdev_initialize();
+
ovs_mutex_lock(&netdev_class_mutex);
rc = netdev_lookup_class(type);
if (!rc) {
* Returns EAGAIN immediately if no packet is ready to be received.
*
* Returns EMSGSIZE, and discards the packet, if the received packet is longer
- * than 'ofpbuf_tailroom(buffer)'.
+ * than 'dp_packet_tailroom(buffer)'.
*
* It is advised that the tailroom of 'buffer' should be
* VLAN_HEADER_LEN bytes longer than the MTU to allow space for an
/* Configures the number of tx queues and rx queues of 'netdev'.
* Return 0 if successful, otherwise a positive errno value.
*
+ * 'n_rxq' specifies the maximum number of receive queues to create.
+ * The netdev provider might choose to create less (e.g. if the hardware
+ * supports only a smaller number). The caller can check how many have been
+ * actually created by calling 'netdev_n_rxq()'
+ *
+ * 'n_txq' specifies the exact number of transmission queues to create.
+ * If this function returns successfully, the caller can make 'n_txq'
+ * concurrent calls to netdev_send() (each one with a different 'qid' in the
+ * range [0..'n_txq'-1]).
+ *
* On error, the tx queue and rx queue configuration is indeterminant.
* Caller should make decision on whether to restore the previous or
* the default configuration. Also, caller must make sure there is no
int
netdev_pop_header(struct netdev *netdev, struct dp_packet **buffers, int cnt)
{
- return (netdev->netdev_class->pop_header
- ? netdev->netdev_class->pop_header(netdev, buffers, cnt)
- : EOPNOTSUPP);
+ int i;
+
+ if (!netdev->netdev_class->pop_header) {
+ return EOPNOTSUPP;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ int err;
+
+ err = netdev->netdev_class->pop_header(buffers[i]);
+ if (err) {
+ dp_packet_clear(buffers[i]);
+ }
+ }
+
+ return 0;
}
int
-netdev_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data)
+netdev_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *data,
+ const struct flow *tnl_flow)
{
if (netdev->netdev_class->build_header) {
- return netdev->netdev_class->build_header(netdev, data);
+ return netdev->netdev_class->build_header(netdev, data, tnl_flow);
}
return EOPNOTSUPP;
}
struct dp_packet **buffers, int cnt,
const struct ovs_action_push_tnl *data)
{
- if (netdev->netdev_class->push_header) {
- return netdev->netdev_class->push_header(netdev, buffers, cnt, data);
- } else {
+ int i;
+
+ if (!netdev->netdev_class->push_header) {
return -EINVAL;
}
+
+ for (i = 0; i < cnt; i++) {
+ netdev->netdev_class->push_header(buffers[i], data);
+ buffers[i]->md = PKT_METADATA_INITIALIZER(u32_to_odp(data->out_port));
+ }
+
+ return 0;
}
/* Registers with the poll loop to wake up from the next call to poll_block()