netdev: New function netdev_get_dpif_port().
[sliver-openvswitch.git] / lib / dpif-netdev.c
index a294ffc..038dfdc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
 #include <config.h>
 #include "dpif.h"
 
-#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -41,6 +40,7 @@
 #include "hmap.h"
 #include "list.h"
 #include "netdev.h"
+#include "netdev-vport.h"
 #include "netlink.h"
 #include "odp-util.h"
 #include "ofp-print.h"
@@ -160,7 +160,7 @@ static void dp_netdev_execute_actions(struct dp_netdev *,
 static struct dpif_netdev *
 dpif_netdev_cast(const struct dpif *dpif)
 {
-    assert(dpif->dpif_class->open == dpif_netdev_open);
+    ovs_assert(dpif->dpif_class->open == dpif_netdev_open);
     return CONTAINER_OF(dpif, struct dpif_netdev, dpif);
 }
 
@@ -181,6 +181,20 @@ dpif_netdev_enumerate(struct sset *all_dps)
     return 0;
 }
 
+static bool
+dpif_netdev_class_is_dummy(const struct dpif_class *class)
+{
+    return class != &dpif_netdev_class;
+}
+
+static const char *
+dpif_netdev_port_open_type(const struct dpif_class *class, const char *type)
+{
+    return strcmp(type, "internal") ? type
+                  : dpif_netdev_class_is_dummy(class) ? "dummy"
+                  : "tap";
+}
+
 static struct dpif *
 create_dpif_netdev(struct dp_netdev *dp)
 {
@@ -281,7 +295,7 @@ dpif_netdev_open(const struct dpif_class *class, const char *name,
             if (error) {
                 return error;
             }
-            assert(dp != NULL);
+            ovs_assert(dp != NULL);
         }
     } else {
         if (dp->class != class) {
@@ -329,7 +343,7 @@ static void
 dpif_netdev_close(struct dpif *dpif)
 {
     struct dp_netdev *dp = get_dp_netdev(dpif);
-    assert(dp->open_cnt > 0);
+    ovs_assert(dp->open_cnt > 0);
     if (--dp->open_cnt == 0 && dp->destroyed) {
         shash_find_and_delete(&dp_netdevs, dp->name);
         dp_netdev_free(dp);
@@ -369,9 +383,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
     /* XXX reject devices already in some dp_netdev. */
 
     /* Open and validate network device. */
-    open_type = (strcmp(type, "internal") ? type
-                 : dp->class != &dpif_netdev_class ? "dummy"
-                 : "tap");
+    open_type = dpif_netdev_port_open_type(dp->class, type);
     error = netdev_open(devname, open_type, &netdev);
     if (error) {
         return error;
@@ -380,7 +392,8 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
     /* XXX reject non-Ethernet devices */
 
     error = netdev_listen(netdev);
-    if (error) {
+    if (error
+        && !(error == EOPNOTSUPP && dpif_netdev_class_is_dummy(dp->class))) {
         VLOG_ERR("%s: cannot receive packets on this network device (%s)",
                  devname, strerror(errno));
         netdev_close(netdev);
@@ -425,11 +438,11 @@ dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
         }
         port_no = *port_nop;
     } else {
-        port_no = choose_port(dp, netdev_get_name(netdev));
+        port_no = choose_port(dp, netdev_vport_get_dpif_port(netdev));
     }
     if (port_no >= 0) {
         *port_nop = port_no;
-        return do_add_port(dp, netdev_get_name(netdev),
+        return do_add_port(dp, netdev_vport_get_dpif_port(netdev),
                            netdev_get_type(netdev), port_no);
     }
     return EFBIG;
@@ -468,7 +481,7 @@ get_port_by_name(struct dp_netdev *dp,
     struct dp_netdev_port *port;
 
     LIST_FOR_EACH (port, node, &dp->port_list) {
-        if (!strcmp(netdev_get_name(port->netdev), devname)) {
+        if (!strcmp(netdev_vport_get_dpif_port(port->netdev), devname)) {
             *portp = port;
             return 0;
         }
@@ -492,7 +505,7 @@ do_del_port(struct dp_netdev *dp, uint32_t port_no)
     dp->ports[port->port_no] = NULL;
     dp->serial++;
 
-    name = xstrdup(netdev_get_name(port->netdev));
+    name = xstrdup(netdev_vport_get_dpif_port(port->netdev));
     netdev_close(port->netdev);
     free(port->type);
 
@@ -506,7 +519,7 @@ static void
 answer_port_query(const struct dp_netdev_port *port,
                   struct dpif_port *dpif_port)
 {
-    dpif_port->name = xstrdup(netdev_get_name(port->netdev));
+    dpif_port->name = xstrdup(netdev_vport_get_dpif_port(port->netdev));
     dpif_port->type = xstrdup(port->type);
     dpif_port->port_no = port->port_no;
 }
@@ -597,7 +610,7 @@ dpif_netdev_port_dump_next(const struct dpif *dpif, void *state_,
         struct dp_netdev_port *port = dp->ports[port_no];
         if (port) {
             free(state->name);
-            state->name = xstrdup(netdev_get_name(port->netdev));
+            state->name = xstrdup(netdev_vport_get_dpif_port(port->netdev));
             dpif_port->name = state->name;
             dpif_port->type = port->type;
             dpif_port->port_no = port->port_no;
@@ -664,7 +677,7 @@ static int
 dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
                               struct flow *flow)
 {
-    if (odp_flow_key_to_flow(key, key_len, flow)) {
+    if (odp_flow_key_to_flow(key, key_len, flow) != ODP_FIT_PERFECT) {
         /* This should not happen: it indicates that odp_flow_key_from_flow()
          * and odp_flow_key_to_flow() disagree on the acceptable form of a
          * flow.  Log the problem as an error, with enough details to enable
@@ -923,7 +936,7 @@ dpif_netdev_execute(struct dpif *dpif, const struct dpif_execute *execute)
     ofpbuf_reserve(&copy, DP_NETDEV_HEADROOM);
     ofpbuf_put(&copy, execute->packet->data, execute->packet->size);
 
-    flow_extract(&copy, 0, NULL, -1, &key);
+    flow_extract(&copy, 0, 0, NULL, -1, &key);
     error = dpif_netdev_flow_from_nlattrs(execute->key, execute->key_len,
                                           &key);
     if (!error) {
@@ -1021,7 +1034,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port,
     if (packet->size < ETH_HEADER_LEN) {
         return;
     }
-    flow_extract(packet, 0, NULL, port->port_no, &key);
+    flow_extract(packet, 0, 0, NULL, port->port_no, &key);
     flow = dp_netdev_lookup_flow(dp, &key);
     if (flow) {
         dp_netdev_flow_used(flow, packet);
@@ -1056,7 +1069,8 @@ dpif_netdev_run(struct dpif *dpif)
         } else if (error != EAGAIN && error != EOPNOTSUPP) {
             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
             VLOG_ERR_RL(&rl, "error receiving data from %s: %s",
-                        netdev_get_name(port->netdev), strerror(error));
+                        netdev_vport_get_dpif_port(port->netdev),
+                        strerror(error));
         }
     }
     ofpbuf_uninit(&packet);
@@ -1186,7 +1200,8 @@ execute_set_action(struct ofpbuf *packet, const struct nlattr *a)
     switch (type) {
     case OVS_KEY_ATTR_TUN_ID:
     case OVS_KEY_ATTR_PRIORITY:
-    case OVS_KEY_ATTR_IPV4_TUNNEL:
+    case OVS_KEY_ATTR_SKB_MARK:
+    case OVS_KEY_ATTR_TUNNEL:
         /* not implemented */
         break;
 
@@ -1243,7 +1258,6 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
     unsigned int left;
 
     NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) {
-        const struct ovs_action_push_vlan *vlan;
         int type = nl_attr_type(a);
 
         switch ((enum ovs_action_attr) type) {
@@ -1255,10 +1269,11 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
             dp_netdev_action_userspace(dp, packet, key, a);
             break;
 
-        case OVS_ACTION_ATTR_PUSH_VLAN:
-            vlan = nl_attr_get(a);
+        case OVS_ACTION_ATTR_PUSH_VLAN: {
+            const struct ovs_action_push_vlan *vlan = nl_attr_get(a);
             eth_push_vlan(packet, vlan->vlan_tci);
             break;
+        }
 
         case OVS_ACTION_ATTR_POP_VLAN:
             eth_pop_vlan(packet);
@@ -1282,6 +1297,7 @@ dp_netdev_execute_actions(struct dp_netdev *dp,
 const struct dpif_class dpif_netdev_class = {
     "netdev",
     dpif_netdev_enumerate,
+    dpif_netdev_port_open_type,
     dpif_netdev_open,
     dpif_netdev_close,
     dpif_netdev_destroy,