-static struct netdev_class netdev_dpdk_class = {
- "dpdk",
- dpdk_class_init, /* init */
- NULL, /* netdev_dpdk_run */
- NULL, /* netdev_dpdk_wait */
-
- netdev_dpdk_alloc,
- netdev_dpdk_construct,
- netdev_dpdk_destruct,
- netdev_dpdk_dealloc,
- netdev_dpdk_get_config,
- NULL, /* netdev_dpdk_set_config */
- NULL, /* get_tunnel_config */
-
- netdev_dpdk_send, /* send */
- NULL, /* send_wait */
-
- netdev_dpdk_set_etheraddr,
- netdev_dpdk_get_etheraddr,
- netdev_dpdk_get_mtu,
- netdev_dpdk_set_mtu,
- netdev_dpdk_get_ifindex,
- netdev_dpdk_get_carrier,
- netdev_dpdk_get_carrier_resets,
- netdev_dpdk_set_miimon,
- netdev_dpdk_get_stats,
- netdev_dpdk_set_stats,
- netdev_dpdk_get_features,
- NULL, /* set_advertisements */
-
- NULL, /* set_policing */
- NULL, /* get_qos_types */
- NULL, /* get_qos_capabilities */
- NULL, /* get_qos */
- NULL, /* set_qos */
- NULL, /* get_queue */
- NULL, /* set_queue */
- NULL, /* delete_queue */
- NULL, /* get_queue_stats */
- NULL, /* queue_dump_start */
- NULL, /* queue_dump_next */
- NULL, /* queue_dump_done */
- NULL, /* dump_queue_stats */
-
- NULL, /* get_in4 */
- NULL, /* set_in4 */
- NULL, /* get_in6 */
- NULL, /* add_router */
- NULL, /* get_next_hop */
- netdev_dpdk_get_status,
- NULL, /* arp_lookup */
-
- netdev_dpdk_update_flags,
-
- netdev_dpdk_rxq_alloc,
- netdev_dpdk_rxq_construct,
- netdev_dpdk_rxq_destruct,
- netdev_dpdk_rxq_dealloc,
- netdev_dpdk_rxq_recv,
- NULL, /* rxq_wait */
- NULL, /* rxq_drain */
-};
+static int
+dpdk_ring_open(const char dev_name[], unsigned int *eth_port_id) OVS_REQUIRES(dpdk_mutex)
+{
+ struct dpdk_ring *ivshmem;
+ unsigned int port_no;
+ int err = 0;
+
+ /* Names always start with "dpdkr" */
+ err = dpdk_dev_parse_name(dev_name, "dpdkr", &port_no);
+ if (err) {
+ return err;
+ }
+
+ /* look through our list to find the device */
+ LIST_FOR_EACH (ivshmem, list_node, &dpdk_ring_list) {
+ if (ivshmem->user_port_id == port_no) {
+ VLOG_INFO("Found dpdk ring device %s:", dev_name);
+ *eth_port_id = ivshmem->eth_port_id; /* really all that is needed */
+ return 0;
+ }
+ }
+ /* Need to create the device rings */
+ return dpdk_ring_create(dev_name, port_no, eth_port_id);
+}
+
+static int
+netdev_dpdk_ring_send(struct netdev *netdev_, int qid,
+ struct dp_packet **pkts, int cnt, bool may_steal)
+{
+ struct netdev_dpdk *netdev = netdev_dpdk_cast(netdev_);
+ unsigned i;
+
+ /* When using 'dpdkr' and sending to a DPDK ring, we want to ensure that the
+ * rss hash field is clear. This is because the same mbuf may be modified by
+ * the consumer of the ring and return into the datapath without recalculating
+ * the RSS hash. */
+ for (i = 0; i < cnt; i++) {
+ dp_packet_rss_invalidate(pkts[i]);
+ }
+
+ netdev_dpdk_send__(netdev, qid, pkts, cnt, may_steal);
+ return 0;
+}
+
+static int
+netdev_dpdk_ring_construct(struct netdev *netdev)
+{
+ unsigned int port_no = 0;
+ int err = 0;
+
+ if (rte_eal_init_ret) {
+ return rte_eal_init_ret;
+ }
+
+ ovs_mutex_lock(&dpdk_mutex);
+
+ err = dpdk_ring_open(netdev->name, &port_no);
+ if (err) {
+ goto unlock_dpdk;
+ }
+
+ err = netdev_dpdk_init(netdev, port_no, DPDK_DEV_ETH);
+
+unlock_dpdk:
+ ovs_mutex_unlock(&dpdk_mutex);
+ return err;
+}
+
+#define NETDEV_DPDK_CLASS(NAME, INIT, CONSTRUCT, DESTRUCT, MULTIQ, SEND, \
+ GET_CARRIER, GET_STATS, GET_FEATURES, GET_STATUS, RXQ_RECV) \
+{ \
+ NAME, \
+ INIT, /* init */ \
+ NULL, /* netdev_dpdk_run */ \
+ NULL, /* netdev_dpdk_wait */ \
+ \
+ netdev_dpdk_alloc, \
+ CONSTRUCT, \
+ DESTRUCT, \
+ netdev_dpdk_dealloc, \
+ netdev_dpdk_get_config, \
+ netdev_dpdk_set_config, \
+ NULL, /* get_tunnel_config */ \
+ NULL, /* build header */ \
+ NULL, /* push header */ \
+ NULL, /* pop header */ \
+ netdev_dpdk_get_numa_id, /* get_numa_id */ \
+ MULTIQ, /* set_multiq */ \
+ \
+ SEND, /* send */ \
+ NULL, /* send_wait */ \
+ \
+ netdev_dpdk_set_etheraddr, \
+ netdev_dpdk_get_etheraddr, \
+ netdev_dpdk_get_mtu, \
+ netdev_dpdk_set_mtu, \
+ netdev_dpdk_get_ifindex, \
+ GET_CARRIER, \
+ netdev_dpdk_get_carrier_resets, \
+ netdev_dpdk_set_miimon, \
+ GET_STATS, \
+ GET_FEATURES, \
+ NULL, /* set_advertisements */ \
+ \
+ NULL, /* set_policing */ \
+ NULL, /* get_qos_types */ \
+ NULL, /* get_qos_capabilities */ \
+ NULL, /* get_qos */ \
+ NULL, /* set_qos */ \
+ NULL, /* get_queue */ \
+ NULL, /* set_queue */ \
+ NULL, /* delete_queue */ \
+ NULL, /* get_queue_stats */ \
+ NULL, /* queue_dump_start */ \
+ NULL, /* queue_dump_next */ \
+ NULL, /* queue_dump_done */ \
+ NULL, /* dump_queue_stats */ \
+ \
+ NULL, /* get_in4 */ \
+ NULL, /* set_in4 */ \
+ NULL, /* get_in6 */ \
+ NULL, /* add_router */ \
+ NULL, /* get_next_hop */ \
+ GET_STATUS, \
+ NULL, /* arp_lookup */ \
+ \
+ netdev_dpdk_update_flags, \
+ \
+ netdev_dpdk_rxq_alloc, \
+ netdev_dpdk_rxq_construct, \
+ netdev_dpdk_rxq_destruct, \
+ netdev_dpdk_rxq_dealloc, \
+ RXQ_RECV, \
+ NULL, /* rx_wait */ \
+ NULL, /* rxq_drain */ \
+}
+
+static int
+process_vhost_flags(char *flag, char *default_val, int size,
+ char **argv, char **new_val)
+{
+ int changed = 0;
+
+ /* Depending on which version of vhost is in use, process the vhost-specific
+ * flag if it is provided on the vswitchd command line, otherwise resort to
+ * a default value.
+ *
+ * For vhost-user: Process "-vhost_sock_dir" to set the custom location of
+ * the vhost-user socket(s).
+ * For vhost-cuse: Process "-cuse_dev_name" to set the custom name of the
+ * vhost-cuse character device.
+ */
+ if (!strcmp(argv[1], flag) && (strlen(argv[2]) <= size)) {
+ changed = 1;
+ *new_val = xstrdup(argv[2]);
+ VLOG_INFO("User-provided %s in use: %s", flag, *new_val);
+ } else {
+ VLOG_INFO("No %s provided - defaulting to %s", flag, default_val);
+ *new_val = default_val;
+ }
+
+ return changed;
+}