[ovs-dev] [PATCH 4/7] lib/netdev-windows.c: add code to query netdev information

Ankur Sharma ankursharma at vmware.com
Fri Oct 3 23:57:42 UTC 2014


Acked-by: Ankur Sharma <ankursharma at vmware.com>
________________________________
From: Nithin Raju
Sent: Friday, October 3, 2014 4:55 PM
To: Ankur Sharma
Subject: Fwd: [PATCH 4/7] lib/netdev-windows.c: add code to query netdev information



Begin forwarded message:

From: Nithin Raju <nithin at vmware.com<mailto:nithin at vmware.com>>
Subject: [PATCH 4/7] lib/netdev-windows.c: add code to query netdev information
Date: September 30, 2014 6:00:04 PM PDT
To: <dev at openvswitch.org<mailto:dev at openvswitch.org>>
Cc: Nithin Raju <nithin at vmware.com<mailto:nithin at vmware.com>>

Primary goals of netdev-windows.c are:
1) To query the 'network device' information of a vport such as MTU, etc.
2) Monitor changes to the 'network device' information such as link
 status.

In this change, we implement only #1. #2 can also be implemented, but it
does not seem to be required for the purposes of implement
'ovs-dpctl.exe show'.

Signed-off-by: Nithin Raju <nithin at vmware.com<mailto:nithin at vmware.com>>
---
lib/netdev-windows.c |  223 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 218 insertions(+), 5 deletions(-)

diff --git a/lib/netdev-windows.c b/lib/netdev-windows.c
index 33209b1..5af78c1 100644
--- a/lib/netdev-windows.c
+++ b/lib/netdev-windows.c
@@ -73,39 +73,251 @@ struct netdev_windows_netdev_info {
    uint32_t ifi_flags;
};

+static int refresh_port_status(struct netdev_windows *netdev);
+static int query_netdev(const char *devname,
+                        struct netdev_windows_netdev_info *reply,
+                        struct ofpbuf **bufp);
+static int netdev_windows_init(void);
+
+/* Generic Netlink family numbers for OVS.
+ *
+ * Initialized by netdev_windows_init(). */
+static int ovs_win_netdev_family;
+struct nl_sock *ovs_win_netdev_sock;
+
+
+static bool
+is_netdev_windows_class(const struct netdev_class *netdev_class)
+{
+    return netdev_class->init == netdev_windows_init;
+}
+
+static struct netdev_windows *
+netdev_windows_cast(const struct netdev *netdev_)
+{
+    ovs_assert(is_netdev_windows_class(netdev_get_class(netdev_)));
+    return CONTAINER_OF(netdev_, struct netdev_windows, up);
+}
+
static int
netdev_windows_init(void)
{
-    return EINVAL;
+    int error = 0;
+    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
+
+    if (ovsthread_once_start(&once)) {
+        error = nl_lookup_genl_family(OVS_WIN_NETDEV_FAMILY,
+                                      &ovs_win_netdev_family);
+        if (error) {
+            VLOG_ERR("Generic Netlink family '%s' does not exist. "
+                     "The Open vSwitch kernel module is probably not loaded.",
+                     OVS_WIN_NETDEV_FAMILY);
+        }
+        if (!error) {
+            /* XXX: Where to close this socket? */
+            error = nl_sock_create(NETLINK_GENERIC, &ovs_win_netdev_sock);
+        }
+
+        ovsthread_once_done(&once);
+    }
+
+    return error;
}

static struct netdev *
netdev_windows_alloc(void)
{
-    return NULL;
+    struct netdev_windows *netdev = xzalloc(sizeof *netdev);
+    return &netdev->up;
}

static int
netdev_windows_system_construct(struct netdev *netdev_)
{
-    return EINVAL;
+    struct netdev_windows *netdev = netdev_windows_cast(netdev_);
+    uint8_t mac[ETH_ADDR_LEN];
+    struct netdev_windows_netdev_info info;
+    struct ofpbuf *bufp;
+    int ret;
+
+    /* Query the attributes and runtime status of the netdev. */
+    ret = query_netdev(netdev_get_name(&netdev->up), &info, &bufp);
+    if (ret) {
+        return ret;
+    }
+
+    netdev->change_seq = 1;
+    netdev->dev_type = info.ovs_type;
+    netdev->port_no = info.port_no;
+
+    memcpy(netdev->mac, info.mac_address, ETH_ADDR_LEN);
+    netdev->cache_valid = VALID_ETHERADDR;
+    netdev->ifindex = -EOPNOTSUPP;
+
+    netdev->mtu = info.mtu;
+    netdev->cache_valid |= VALID_MTU;
+
+    netdev->ifi_flags = info.ifi_flags;
+    netdev->cache_valid |= VALID_IFFLAG;
+
+    VLOG_DBG("construct device %s, ovs_type: %u.",
+             netdev_get_name(&netdev->up), info.ovs_type);
+    return 0;
+}
+
+static int
+netdev_windows_netdev_to_ofpbuf(struct netdev_windows_netdev_info *info,
+                                struct ofpbuf *buf)
+{
+    struct ovs_header *ovs_header;
+    int error = EINVAL;
+
+    nl_msg_put_genlmsghdr(buf, 0, ovs_win_netdev_family,
+                          NLM_F_REQUEST | NLM_F_ECHO,
+                          info->cmd, OVS_WIN_NETDEV_VERSION);
+
+    ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header);
+    ovs_header->dp_ifindex = info->dp_ifindex;
+
+    if (info->name) {
+        nl_msg_put_string(buf, OVS_WIN_NETDEV_ATTR_NAME, info->name);
+        error = 0;
+    }
+
+    return error;
+}
+
+static void
+netdev_windows_info_init(struct netdev_windows_netdev_info *info)
+{
+    memset(info, 0, sizeof *info);
+}
+
+static int
+netdev_windows_netdev_from_ofpbuf(struct netdev_windows_netdev_info *info,
+                                  struct ofpbuf *buf)
+{
+    static const struct nl_policy ovs_netdev_policy[] = {
+        [OVS_WIN_NETDEV_ATTR_PORT_NO] = { .type = NL_A_U32 },
+        [OVS_WIN_NETDEV_ATTR_TYPE] = { .type = NL_A_U32 },
+        [OVS_WIN_NETDEV_ATTR_NAME] = { .type = NL_A_STRING, .max_len = IFNAMSIZ },
+        [OVS_WIN_NETDEV_ATTR_MAC_ADDR] = { NL_POLICY_FOR(info->mac_address) },
+        [OVS_WIN_NETDEV_ATTR_MTU] = { .type = NL_A_U32 },
+        [OVS_WIN_NETDEV_ATTR_IF_FLAGS] = { .type = NL_A_U32 },
+    };
+
+    struct nlattr *a[ARRAY_SIZE(ovs_netdev_policy)];
+    struct ovs_header *ovs_header;
+    struct nlmsghdr *nlmsg;
+    struct genlmsghdr *genl;
+    struct ofpbuf b;
+
+    netdev_windows_info_init(info);
+
+    ofpbuf_use_const(&b, ofpbuf_data(buf), ofpbuf_size(buf));
+    nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
+    genl = ofpbuf_try_pull(&b, sizeof *genl);
+    ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
+    if (!nlmsg || !genl || !ovs_header
+        || nlmsg->nlmsg_type != ovs_win_netdev_family
+        || !nl_policy_parse(&b, 0, ovs_netdev_policy, a,
+                            ARRAY_SIZE(ovs_netdev_policy))) {
+        return EINVAL;
+    }
+
+    info->cmd = genl->cmd;
+    info->dp_ifindex = ovs_header->dp_ifindex;
+    info->port_no = nl_attr_get_odp_port(a[OVS_WIN_NETDEV_ATTR_PORT_NO]);
+    info->ovs_type = nl_attr_get_u32(a[OVS_WIN_NETDEV_ATTR_TYPE]);
+    info->name = nl_attr_get_string(a[OVS_WIN_NETDEV_ATTR_NAME]);
+    memcpy(info->mac_address, nl_attr_get_string(a[OVS_WIN_NETDEV_ATTR_NAME]),
+           sizeof(info->mac_address));
+    info->mtu = nl_attr_get_u32(a[OVS_WIN_NETDEV_ATTR_MTU]);
+    info->ifi_flags = nl_attr_get_u32(a[OVS_WIN_NETDEV_ATTR_IF_FLAGS]);
+
+    return 0;
+}
+
+static int
+query_netdev(const char *devname,
+             struct netdev_windows_netdev_info *info,
+             struct ofpbuf **bufp)
+{
+    int error = 0;
+    struct ofpbuf *request_buf;
+
+    ovs_assert(info != NULL);
+    netdev_windows_info_init(info);
+
+    error = netdev_windows_init();
+    if (error) {
+        if (info) {
+            *bufp = NULL;
+            netdev_windows_info_init(info);
+        }
+        return error;
+    }
+
+    request_buf = ofpbuf_new(1024);
+    info->cmd = OVS_WIN_NETDEV_CMD_GET;
+    info->name = devname;
+    netdev_windows_netdev_to_ofpbuf(info, request_buf);
+    error = nl_transact(NETLINK_GENERIC, request_buf, bufp);
+    ofpbuf_delete(request_buf);
+
+    if (info) {
+        if (!error) {
+            error = netdev_windows_netdev_from_ofpbuf(info, *bufp);
+        }
+        if (error) {
+            netdev_windows_info_init(info);
+            ofpbuf_delete(*bufp);
+            *bufp = NULL;
+        }
+    }
+
+    return 0;
+}
+
+static void
+netdev_windows_destruct(struct netdev *netdev_)
+{
+
}

static void
netdev_windows_dealloc(struct netdev *netdev_)
{
+    struct netdev_windows *netdev = netdev_windows_cast(netdev_);
+    free(netdev);
}

static int
netdev_windows_get_etheraddr(const struct netdev *netdev_, uint8_t mac[6])
{
-    return EINVAL;
+    struct netdev_windows *netdev = netdev_windows_cast(netdev_);
+
+    ovs_assert((netdev->cache_valid & VALID_ETHERADDR) != 0);
+    if (netdev->cache_valid & VALID_ETHERADDR) {
+        memcpy(mac, netdev->mac, ETH_ADDR_LEN);
+    } else {
+        return EINVAL;
+    }
+    return 0;
}

static int
netdev_windows_get_mtu(const struct netdev *netdev_, int *mtup)
{
-    return EINVAL;
+    struct netdev_windows *netdev = netdev_windows_cast(netdev_);
+
+    ovs_assert((netdev->cache_valid & VALID_MTU) != 0);
+    if (netdev->cache_valid & VALID_MTU) {
+        *mtup = netdev->mtu;
+    } else {
+        return EINVAL;
+    }
+    return 0;
}


@@ -122,6 +334,7 @@ netdev_windows_internal_construct(struct netdev *netdev_)
    .init               = netdev_windows_init,                          \
    .alloc              = netdev_windows_alloc,                         \
    .construct          = CONSTRUCT,                                    \
+    .destruct           = netdev_windows_destruct,                      \
    .dealloc            = netdev_windows_dealloc,                       \
    .get_etheraddr      = netdev_windows_get_etheraddr,                 \
}
--
1.7.4.1


Thanks,
-- Nithin




More information about the dev mailing list