#include "ovs-atomic.h"
#include "packets.h"
#include "pcap-file.h"
-#include "poll-loop.h"
+#include "openvswitch/poll-loop.h"
#include "openvswitch/shash.h"
#include "sset.h"
#include "stream.h"
struct dummy_packet_stream {
struct stream *stream;
- struct dp_packet rxbuf;
struct ovs_list txq;
+ struct dp_packet rxbuf;
};
enum dummy_packet_conn_type {
ovs_mutex_unlock(&dummy_list_mutex);
ovs_mutex_lock(&netdev->mutex);
+ if (netdev->rxq_pcap) {
+ fclose(netdev->rxq_pcap);
+ }
+ if (netdev->tx_pcap && netdev->tx_pcap != netdev->rxq_pcap) {
+ fclose(netdev->tx_pcap);
+ }
dummy_packet_conn_close(&netdev->conn);
netdev->conn.type = NONE;
static int
netdev_dummy_send(struct netdev *netdev, int qid OVS_UNUSED,
- struct dp_packet_batch *batch, bool may_steal,
+ struct dp_packet_batch *batch,
bool concurrent_txq OVS_UNUSED)
{
struct netdev_dummy *dev = netdev_dummy_cast(netdev);
break;
}
- size -= dp_packet_get_cutlen(packet);
-
if (size < ETH_HEADER_LEN) {
error = EMSGSIZE;
break;
/* Reply to ARP requests for 'dev''s assigned IP address. */
if (dev->address.s_addr) {
- struct dp_packet packet;
+ struct dp_packet dp;
struct flow flow;
- dp_packet_use_const(&packet, buffer, size);
- flow_extract(&packet, &flow);
+ dp_packet_use_const(&dp, buffer, size);
+ flow_extract(&dp, &flow);
if (flow.dl_type == htons(ETH_TYPE_ARP)
&& flow.nw_proto == ARP_OP_REQUEST
&& flow.nw_dst == dev->address.s_addr) {
}
if (dev->tx_pcap) {
- struct dp_packet packet;
+ struct dp_packet dp;
- dp_packet_use_const(&packet, buffer, size);
- ovs_pcap_write(dev->tx_pcap, &packet);
+ dp_packet_use_const(&dp, buffer, size);
+ ovs_pcap_write(dev->tx_pcap, &dp);
fflush(dev->tx_pcap);
}
ovs_mutex_unlock(&dev->mutex);
}
- dp_packet_delete_batch(batch, may_steal);
+ dp_packet_delete_batch(batch, true);
return error;
}
\
NULL, /* get_features */ \
NULL, /* set_advertisements */ \
+ NULL, /* get_pt_mode */ \
\
NULL, /* set_policing */ \
NULL, /* get_qos_types */ \
netdev_dummy_rxq_recv, \
netdev_dummy_rxq_wait, \
netdev_dummy_rxq_drain, \
+ \
+ NO_OFFLOAD_API \
}
static const struct netdev_class dummy_class =
}
static struct dp_packet *
-eth_from_flow(const char *s)
+eth_from_flow(const char *s, size_t packet_size)
{
enum odp_key_fitness fitness;
struct dp_packet *packet;
}
packet = dp_packet_new(0);
- flow_compose(packet, &flow);
+ if (!flow_compose(packet, &flow, packet_size)) {
+ dp_packet_delete(packet);
+ packet = NULL;
+ };
ofpbuf_uninit(&odp_key);
return packet;
packet = eth_from_packet(argv[i]);
if (!packet) {
+ int packet_size = 0;
+ const char *flow_str = argv[i];
+
+ /* Parse optional --len argument immediately follows a 'flow'. */
+ if (argc >= i + 2 && !strcmp(argv[i + 1], "--len")) {
+ packet_size = strtol(argv[i + 2], NULL, 10);
+
+ if (packet_size < ETH_TOTAL_MIN) {
+ unixctl_command_reply_error(conn, "too small packet len");
+ goto exit;
+ }
+ i += 2;
+ }
/* Try parse 'argv[i]' as odp flow. */
- packet = eth_from_flow(argv[i]);
+ packet = eth_from_flow(flow_str, packet_size);
if (!packet) {
unixctl_command_reply_error(conn, "bad packet or flow syntax");
goto exit;
}
-
- /* Parse optional --len argument immediately follows a 'flow'. */
- if (argc >= i + 2 && !strcmp(argv[i + 1], "--len")) {
- int packet_size = strtol(argv[i + 2], NULL, 10);
- dp_packet_set_size(packet, packet_size);
- i+=2;
- }
}
netdev_dummy_queue_packet(dummy_dev, packet, rx_qid);
unixctl_command_reply_error(conn, error);
free(error);
}
- netdev_close(netdev);
} else {
unixctl_command_reply_error(conn, "Unknown Dummy Interface");
}