Merge remote-tracking branch 'origin/master' into ovn4
[cascardo/ovs.git] / lib / netdev.c
index 444ae85..42e5d8a 100644 (file)
@@ -26,6 +26,7 @@
 
 #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 "seq.h"
 #include "shash.h"
 #include "smap.h"
 #include "sset.h"
 #include "svec.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
+#include "flow.h"
 
 VLOG_DEFINE_THIS_MODULE(netdev);
 
@@ -52,7 +55,7 @@ COVERAGE_DEFINE(netdev_get_stats);
 
 struct netdev_saved_flags {
     struct netdev *netdev;
-    struct list node;           /* In struct netdev's saved_flags_list. */
+    struct ovs_list node;           /* In struct netdev's saved_flags_list. */
     enum netdev_flags saved_flags;
     enum netdev_flags saved_values;
 };
@@ -91,6 +94,12 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
 static void restore_all_flags(void *aux OVS_UNUSED);
 void update_device_args(struct netdev *, const struct shash *args);
 
+int
+netdev_n_txq(const struct netdev *netdev)
+{
+    return netdev->n_txq;
+}
+
 int
 netdev_n_rxq(const struct netdev *netdev)
 {
@@ -101,7 +110,9 @@ bool
 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
@@ -137,6 +148,11 @@ netdev_initialize(void)
 #if defined(__FreeBSD__) || defined(__NetBSD__)
         netdev_register_provider(&netdev_tap_class);
         netdev_register_provider(&netdev_bsd_class);
+#endif
+#ifdef _WIN32
+        netdev_register_provider(&netdev_windows_class);
+        netdev_register_provider(&netdev_internal_class);
+        netdev_vport_tunnel_register();
 #endif
         netdev_dpdk_register();
 
@@ -242,6 +258,8 @@ netdev_unregister_provider(const char *type)
     struct netdev_registered_class *rc;
     int error;
 
+    netdev_initialize();
+
     ovs_mutex_lock(&netdev_class_mutex);
     rc = netdev_lookup_class(type);
     if (!rc) {
@@ -355,12 +373,10 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
                 netdev->change_seq = 1;
                 netdev->node = shash_add(&netdev_shash, name, netdev);
 
-                /* By default enable one rx queue per netdev. */
-                if (netdev->netdev_class->rxq_alloc) {
-                    netdev->n_rxq = 1;
-                } else {
-                    netdev->n_rxq = 0;
-                }
+                /* By default enable one tx and rx queue per netdev. */
+                netdev->n_txq = netdev->netdev_class->send ? 1 : 0;
+                netdev->n_rxq = netdev->netdev_class->rxq_alloc ? 1 : 0;
+
                 list_init(&netdev->saved_flags_list);
 
                 error = rc->class->construct(netdev);
@@ -621,7 +637,7 @@ netdev_rxq_close(struct netdev_rxq *rx)
  * 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
@@ -631,7 +647,7 @@ netdev_rxq_close(struct netdev_rxq *rx)
  * This function may be set to null if it would always return EOPNOTSUPP
  * anyhow. */
 int
-netdev_rxq_recv(struct netdev_rxq *rx, struct dpif_packet **buffers, int *cnt)
+netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet **buffers, int *cnt)
 {
     int retval;
 
@@ -659,6 +675,43 @@ netdev_rxq_drain(struct netdev_rxq *rx)
             : 0);
 }
 
+/* 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
+ * other thread accessing the queues at the same time. */
+int
+netdev_set_multiq(struct netdev *netdev, unsigned int n_txq,
+                  unsigned int n_rxq)
+{
+    int error;
+
+    error = (netdev->netdev_class->set_multiq
+             ? netdev->netdev_class->set_multiq(netdev,
+                                                MAX(n_txq, 1),
+                                                MAX(n_rxq, 1))
+             : EOPNOTSUPP);
+
+    if (error && error != EOPNOTSUPP) {
+        VLOG_DBG_RL(&rl, "failed to set tx/rx queue for network device %s:"
+                    "%s", netdev_get_name(netdev), ovs_strerror(error));
+    }
+
+    return error;
+}
+
 /* Sends 'buffers' on 'netdev'.  Returns 0 if successful (for every packet),
  * otherwise a positive errno value.  Returns EAGAIN without blocking if
  * at least one the packets cannot be queued immediately.  Returns EMSGSIZE
@@ -670,19 +723,22 @@ netdev_rxq_drain(struct netdev_rxq *rx)
  *
  * To retain ownership of 'buffer' caller can set may_steal to false.
  *
- * The kernel maintains a packet transmission queue, so the caller is not
- * expected to do additional queuing of packets.
+ * The network device is expected to maintain one or more packet
+ * transmission queues, so that the caller does not ordinarily have to
+ * do additional queuing of packets.  'qid' specifies the queue to use
+ * and can be ignored if the implementation does not support multiple
+ * queues.
  *
  * 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 dpif_packet **buffers, int cnt,
-            bool may_steal)
+netdev_send(struct netdev *netdev, int qid, struct dp_packet **buffers,
+            int cnt, bool may_steal)
 {
     int error;
 
     error = (netdev->netdev_class->send
-             ? netdev->netdev_class->send(netdev, buffers, cnt, may_steal)
+             ? netdev->netdev_class->send(netdev, qid, buffers, cnt, may_steal)
              : EOPNOTSUPP);
     if (!error) {
         COVERAGE_INC(netdev_sent);
@@ -690,18 +746,70 @@ netdev_send(struct netdev *netdev, struct dpif_packet **buffers, int cnt,
     return error;
 }
 
+int
+netdev_pop_header(struct netdev *netdev, struct dp_packet **buffers, int cnt)
+{
+    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,
+                    const struct flow *tnl_flow)
+{
+    if (netdev->netdev_class->build_header) {
+        return netdev->netdev_class->build_header(netdev, data, tnl_flow);
+    }
+    return EOPNOTSUPP;
+}
+
+int
+netdev_push_header(const struct netdev *netdev,
+                   struct dp_packet **buffers, int cnt,
+                   const struct ovs_action_push_tnl *data)
+{
+    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()
  * when the packet transmission queue has sufficient room to transmit a packet
  * with netdev_send().
  *
- * The kernel maintains a packet transmission queue, so the client is not
- * expected to do additional queuing of packets.  Thus, this function is
- * unlikely to ever be used.  It is included for completeness. */
+ * The network device is expected to maintain one or more packet
+ * transmission queues, so that the caller does not ordinarily have to
+ * do additional queuing of packets.  'qid' specifies the queue to use
+ * and can be ignored if the implementation does not support multiple
+ * queues. */
 void
-netdev_send_wait(struct netdev *netdev)
+netdev_send_wait(struct netdev *netdev, int qid)
 {
     if (netdev->netdev_class->send_wait) {
-        netdev->netdev_class->send_wait(netdev);
+        netdev->netdev_class->send_wait(netdev, qid);
     }
 }
 
@@ -1230,19 +1338,6 @@ netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
     return error;
 }
 
-/* Attempts to change the stats for 'netdev' to those provided in 'stats'.
- * Returns 0 if successful, otherwise a positive errno value.
- *
- * This will probably fail for most network devices.  Some devices might only
- * allow setting their stats to 0. */
-int
-netdev_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
-{
-    return (netdev->netdev_class->set_stats
-             ? netdev->netdev_class->set_stats(netdev, stats)
-             : EOPNOTSUPP);
-}
-
 /* Attempts to set input rate limiting (policing) policy, such that up to
  * 'kbits_rate' kbps of traffic is accepted, with a maximum accumulative burst
  * size of 'kbits' kb. */