netdev: Pass class structure, instead of type, to "create" function.
[sliver-openvswitch.git] / lib / netdev-tunnel.c
index 0497cbb..a2383a4 100644 (file)
@@ -39,7 +39,7 @@ struct netdev_tunnel {
     struct netdev netdev;
 };
 
-static int netdev_tunnel_create(const char *name, const char *type,
+static int netdev_tunnel_create(const struct netdev_class *, const char *name,
                                 const struct shash *args, struct netdev_dev **);
 
 static struct netdev_dev_tunnel *
@@ -62,10 +62,13 @@ parse_config(const char *name, const char *type, const struct shash *args,
              struct tnl_port_config *config)
 {
     struct shash_node *node;
+    bool ipsec_ip_set = false;
+    bool ipsec_mech_set = false;
 
     memset(config, 0, sizeof *config);
 
     config->flags |= TNL_F_PMTUD;
+    config->flags |= TNL_F_HDR_CACHE;
 
     SHASH_FOR_EACH (node, args) {
         if (!strcmp(node->name, "remote_ip")) {
@@ -82,20 +85,20 @@ parse_config(const char *name, const char *type, const struct shash *args,
             } else {
                 config->saddr = in_addr.s_addr;
             }
-        } else if (!strcmp(node->name, "key")) {
+        } else if (!strcmp(node->name, "key") && !strcmp(type, "gre")) {
             if (!strcmp(node->data, "flow")) {
                 config->flags |= TNL_F_IN_KEY_MATCH;
                 config->flags |= TNL_F_OUT_KEY_ACTION;
             } else {
                 config->out_key = config->in_key = htonl(atoi(node->data));
             }
-        } else if (!strcmp(node->name, "in_key")) {
+        } else if (!strcmp(node->name, "in_key") && !strcmp(type, "gre")) {
             if (!strcmp(node->data, "flow")) {
                 config->flags |= TNL_F_IN_KEY_MATCH;
             } else {
                 config->in_key = htonl(atoi(node->data));
             }
-        } else if (!strcmp(node->name, "out_key")) {
+        } else if (!strcmp(node->name, "out_key") && !strcmp(type, "gre")) {
             if (!strcmp(node->data, "flow")) {
                 config->flags |= TNL_F_OUT_KEY_ACTION;
             } else {
@@ -113,7 +116,7 @@ parse_config(const char *name, const char *type, const struct shash *args,
             } else {
                 config->ttl = atoi(node->data);
             }
-        } else if (!strcmp(node->name, "csum")) {
+        } else if (!strcmp(node->name, "csum") && !strcmp(type, "gre")) {
             if (!strcmp(node->data, "true")) {
                 config->flags |= TNL_F_CSUM;
             }
@@ -121,11 +124,28 @@ parse_config(const char *name, const char *type, const struct shash *args,
             if (!strcmp(node->data, "false")) {
                 config->flags &= ~TNL_F_PMTUD;
             }
+        } else if (!strcmp(node->name, "header_cache")) {
+            if (!strcmp(node->data, "false")) {
+                config->flags &= ~TNL_F_HDR_CACHE;
+            }
+        } else if (!strcmp(node->name, "ipsec_local_ip")) {
+            ipsec_ip_set = true;
+        } else if (!strcmp(node->name, "ipsec_cert")
+                   || !strcmp(node->name, "ipsec_psk")) {
+            ipsec_mech_set = true;
         } else {
             VLOG_WARN("%s: unknown %s argument '%s'", name, type, node->name);
         }
     }
 
+    /* IPsec doesn't work when header caching is enabled.  Disable it if
+     * the IPsec local IP address and authentication mechanism have been
+     * defined. */
+    if (ipsec_ip_set && ipsec_mech_set) {
+        VLOG_INFO("%s: header caching disabled due to use of IPsec", name);
+        config->flags &= ~TNL_F_HDR_CACHE;
+    }
+
     if (!config->daddr) {
         VLOG_WARN("%s: %s type requires valid 'remote_ip' argument", name, type);
         return EINVAL;
@@ -135,7 +155,7 @@ parse_config(const char *name, const char *type, const struct shash *args,
 }
 
 static int
-netdev_tunnel_create(const char *name, const char *type,
+netdev_tunnel_create(const struct netdev_class *class, const char *name,
                      const struct shash *args, struct netdev_dev **netdev_devp)
 {
     int err;
@@ -143,11 +163,11 @@ netdev_tunnel_create(const char *name, const char *type,
     struct tnl_port_config port_config;
     struct netdev_dev_tunnel *netdev_dev;
 
-    ovs_strlcpy(ova.port_type, type, sizeof ova.port_type);
+    ovs_strlcpy(ova.port_type, class->type, sizeof ova.port_type);
     ovs_strlcpy(ova.devname, name, sizeof ova.devname);
     ova.config = &port_config;
 
-    err = parse_config(name, type, args, &port_config);
+    err = parse_config(name, class->type, args, &port_config);
     if (err) {
         return err;
     }
@@ -169,8 +189,8 @@ netdev_tunnel_create(const char *name, const char *type,
     }
 
     netdev_dev = xmalloc(sizeof *netdev_dev);
-    netdev_dev_init(&netdev_dev->netdev_dev, name, &netdev_gre_class);
 
+    netdev_dev_init(&netdev_dev->netdev_dev, name, class);
     *netdev_devp = &netdev_dev->netdev_dev;
     return 0;
 }
@@ -283,3 +303,63 @@ const struct netdev_class netdev_gre_class = {
     netdev_vport_poll_add,
     netdev_vport_poll_remove,
 };
+
+const struct netdev_class netdev_capwap_class = {
+    "capwap",
+
+    NULL,                       /* init */
+    NULL,                       /* run */
+    NULL,                       /* wait */
+
+    netdev_tunnel_create,
+    netdev_tunnel_destroy,
+    netdev_tunnel_reconfigure,
+
+    netdev_tunnel_open,
+    netdev_tunnel_close,
+
+    NULL,                       /* enumerate */
+
+    NULL,                       /* recv */
+    NULL,                       /* recv_wait */
+    NULL,                       /* drain */
+
+    NULL,                       /* send */
+    NULL,                       /* send_wait */
+
+    netdev_vport_set_etheraddr,
+    netdev_vport_get_etheraddr,
+    netdev_vport_get_mtu,
+    NULL,                       /* get_ifindex */
+    netdev_vport_get_carrier,
+    netdev_vport_get_stats,
+    netdev_vport_set_stats,
+
+    NULL,                       /* get_features */
+    NULL,                       /* set_advertisements */
+    NULL,                       /* get_vlan_vid */
+
+    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,                       /* dump_queues */
+    NULL,                       /* dump_queue_stats */
+
+    NULL,                       /* get_in4 */
+    NULL,                       /* set_in4 */
+    NULL,                       /* get_in6 */
+    NULL,                       /* add_router */
+    NULL,                       /* get_next_hop */
+    NULL,                       /* arp_lookup */
+
+    netdev_vport_update_flags,
+
+    netdev_vport_poll_add,
+    netdev_vport_poll_remove,
+};