netdev-vport: New helper netdev_vport_get_dev().
[sliver-openvswitch.git] / lib / netdev-vport.c
index e50103b..04c3344 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 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.
@@ -81,8 +81,6 @@ static int tnl_port_config_from_nlattr(const struct nlattr *options,
                                        size_t options_len,
                                        struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1]);
 
-static const char *netdev_vport_get_tnl_iface(const struct netdev *netdev);
-
 static bool
 is_vport_class(const struct netdev_class *class)
 {
@@ -103,6 +101,12 @@ netdev_dev_vport_cast(const struct netdev_dev *netdev_dev)
     return CONTAINER_OF(netdev_dev, struct netdev_dev_vport, netdev_dev);
 }
 
+static struct netdev_dev_vport *
+netdev_vport_get_dev(const struct netdev *netdev)
+{
+    return netdev_dev_vport_cast(netdev_get_dev(netdev));
+}
+
 static struct netdev_vport *
 netdev_vport_cast(const struct netdev *netdev)
 {
@@ -137,6 +141,12 @@ netdev_vport_get_vport_type(const struct netdev *netdev)
             : OVS_VPORT_TYPE_UNSPEC);
 }
 
+static uint32_t
+get_u32_or_zero(const struct nlattr *a)
+{
+    return a ? nl_attr_get_u32(a) : 0;
+}
+
 const char *
 netdev_vport_get_netdev_type(const struct dpif_linux_vport *vport)
 {
@@ -160,7 +170,7 @@ netdev_vport_get_netdev_type(const struct dpif_linux_vport *vport)
                                         a)) {
             break;
         }
-        return (nl_attr_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
+        return (get_u32_or_zero(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
                 ? "ipsec_gre" : "gre");
 
     case OVS_VPORT_TYPE_GRE64:
@@ -168,7 +178,7 @@ netdev_vport_get_netdev_type(const struct dpif_linux_vport *vport)
                                         a)) {
             break;
         }
-        return (nl_attr_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
+        return (get_u32_or_zero(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_IPSEC
                 ? "ipsec_gre64" : "gre64");
 
     case OVS_VPORT_TYPE_CAPWAP:
@@ -400,11 +410,26 @@ netdev_vport_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
 }
 
 static int
-netdev_vport_get_drv_info(const struct netdev *netdev, struct smap *smap)
+tunnel_get_status(const struct netdev *netdev, struct smap *smap)
 {
-    const char *iface = netdev_vport_get_tnl_iface(netdev);
+    struct netdev_dev_vport *ndv = netdev_vport_get_dev(netdev);
+    struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1];
+    static char iface[IFNAMSIZ];
+    ovs_be32 route;
+
+    if (!ndv->options) {
+        /* Race condition when 'ndv' was created, but did not have it's
+         * configuration set yet. */
+        return 0;
+    }
+
+    if (tnl_port_config_from_nlattr(ndv->options->data,
+                                    ndv->options->size, a)) {
+        return 0;
+    }
+    route = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
 
-    if (iface) {
+    if (route_table_get_name(route, iface)) {
         struct netdev *egress_netdev;
 
         smap_add(smap, "tunnel_egress_iface", iface);
@@ -435,7 +460,7 @@ netdev_vport_update_flags(struct netdev *netdev OVS_UNUSED,
 static unsigned int
 netdev_vport_change_seq(const struct netdev *netdev)
 {
-    return netdev_dev_vport_cast(netdev_get_dev(netdev))->change_seq;
+    return netdev_vport_get_dev(netdev)->change_seq;
 }
 
 static void
@@ -450,37 +475,12 @@ netdev_vport_wait(void)
     route_table_wait();
 }
 \f
-/* get_tnl_iface() implementation. */
-static const char *
-netdev_vport_get_tnl_iface(const struct netdev *netdev)
-{
-    struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1];
-    ovs_be32 route;
-    struct netdev_dev_vport *ndv;
-    static char name[IFNAMSIZ];
-
-    ndv = netdev_dev_vport_cast(netdev_get_dev(netdev));
-    if (tnl_port_config_from_nlattr(ndv->options->data, ndv->options->size,
-                                    a)) {
-        return NULL;
-    }
-    route = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
-
-    if (route_table_get_name(route, name)) {
-        return name;
-    }
-
-    return NULL;
-}
-\f
 /* Helper functions. */
 
 static void
 netdev_vport_poll_notify(const struct netdev *netdev)
 {
-    struct netdev_dev_vport *ndv;
-
-    ndv = netdev_dev_vport_cast(netdev_get_dev(netdev));
+    struct netdev_dev_vport *ndv = netdev_vport_get_dev(netdev);
 
     ndv->change_seq++;
     if (!ndv->change_seq) {
@@ -694,8 +694,8 @@ tnl_port_config_from_nlattr(const struct nlattr *options, size_t options_len,
                             struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1])
 {
     static const struct nl_policy ovs_tunnel_policy[] = {
-        [OVS_TUNNEL_ATTR_FLAGS] = { .type = NL_A_U32 },
-        [OVS_TUNNEL_ATTR_DST_IPV4] = { .type = NL_A_BE32 },
+        [OVS_TUNNEL_ATTR_FLAGS] = { .type = NL_A_U32, .optional = true },
+        [OVS_TUNNEL_ATTR_DST_IPV4] = { .type = NL_A_BE32, .optional = true },
         [OVS_TUNNEL_ATTR_SRC_IPV4] = { .type = NL_A_BE32, .optional = true },
         [OVS_TUNNEL_ATTR_IN_KEY] = { .type = NL_A_BE64, .optional = true },
         [OVS_TUNNEL_ATTR_OUT_KEY] = { .type = NL_A_BE64, .optional = true },
@@ -725,7 +725,6 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED,
                       struct smap *args)
 {
     struct nlattr *a[OVS_TUNNEL_ATTR_MAX + 1];
-    ovs_be32 daddr;
     uint32_t flags;
     int error;
 
@@ -734,9 +733,10 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED,
         return error;
     }
 
-
-    daddr = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
-    smap_add_format(args, "remote_ip", IP_FMT, IP_ARGS(daddr));
+    if (a[OVS_TUNNEL_ATTR_DST_IPV4]) {
+        ovs_be32 daddr = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]);
+        smap_add_format(args, "remote_ip", IP_FMT, IP_ARGS(daddr));
+    }
 
     if (a[OVS_TUNNEL_ATTR_SRC_IPV4]) {
         ovs_be32 saddr = nl_attr_get_be32(a[OVS_TUNNEL_ATTR_SRC_IPV4]);
@@ -766,7 +766,8 @@ unparse_tunnel_config(const char *name OVS_UNUSED, const char *type OVS_UNUSED,
         }
     }
 
-    flags = nl_attr_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]);
+    flags = get_u32_or_zero(a[OVS_TUNNEL_ATTR_FLAGS]);
+
     if (flags & TNL_F_TTL_INHERIT) {
         smap_add(args, "ttl", "inherit");
     } else if (a[OVS_TUNNEL_ATTR_TTL]) {
@@ -924,27 +925,27 @@ netdev_vport_register(void)
 {
     static const struct vport_class vport_classes[] = {
         { OVS_VPORT_TYPE_GRE,
-          { "gre", VPORT_FUNCTIONS(netdev_vport_get_drv_info) },
+          { "gre", VPORT_FUNCTIONS(tunnel_get_status) },
           parse_tunnel_config, unparse_tunnel_config },
 
         { OVS_VPORT_TYPE_GRE,
-          { "ipsec_gre", VPORT_FUNCTIONS(netdev_vport_get_drv_info) },
+          { "ipsec_gre", VPORT_FUNCTIONS(tunnel_get_status) },
           parse_tunnel_config, unparse_tunnel_config },
 
         { OVS_VPORT_TYPE_GRE64,
-          { "gre64", VPORT_FUNCTIONS(netdev_vport_get_drv_info) },
+          { "gre64", VPORT_FUNCTIONS(tunnel_get_status) },
           parse_tunnel_config, unparse_tunnel_config },
 
         { OVS_VPORT_TYPE_GRE64,
-          { "ipsec_gre64", VPORT_FUNCTIONS(netdev_vport_get_drv_info) },
+          { "ipsec_gre64", VPORT_FUNCTIONS(tunnel_get_status) },
           parse_tunnel_config, unparse_tunnel_config },
 
         { OVS_VPORT_TYPE_CAPWAP,
-          { "capwap", VPORT_FUNCTIONS(netdev_vport_get_drv_info) },
+          { "capwap", VPORT_FUNCTIONS(tunnel_get_status) },
           parse_tunnel_config, unparse_tunnel_config },
 
         { OVS_VPORT_TYPE_VXLAN,
-          { "vxlan", VPORT_FUNCTIONS(netdev_vport_get_drv_info) },
+          { "vxlan", VPORT_FUNCTIONS(tunnel_get_status) },
           parse_tunnel_config, unparse_tunnel_config },
 
         { OVS_VPORT_TYPE_PATCH,