This commit renames the rtnetlink-link.{c,h} to rtnetlink.{c,h}
and extends the module to support RTNLGRP_IPV4_IFADDR and
RTNLGRP_IPV4_IFADDR multicast groups.  A later patch will start
using this module to react to interface address changes.

Signed-off-by: Alex Wang <al...@nicira.com>

---
PATCH->V2:
- new patch, since parsing RTNLGRP_IPV4_IFADDR/RTNLGRP_IPV6_IFADDR
  is different from parsing RTNLGRP_LINK, we need to extend to
  module.
---
 lib/automake.mk                       |    4 +-
 lib/netdev-linux.c                    |   13 ++-
 lib/route-table.c                     |   12 +--
 lib/rtnetlink-link.c                  |  138 -------------------------
 lib/rtnetlink.c                       |  179 +++++++++++++++++++++++++++++++++
 lib/{rtnetlink-link.h => rtnetlink.h} |   39 +++----
 lib/vlandev.c                         |    8 +-
 7 files changed, 219 insertions(+), 174 deletions(-)
 delete mode 100644 lib/rtnetlink-link.c
 create mode 100644 lib/rtnetlink.c
 rename lib/{rtnetlink-link.h => rtnetlink.h} (64%)

diff --git a/lib/automake.mk b/lib/automake.mk
index 018e62c..faca968 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -347,8 +347,8 @@ lib_libopenvswitch_la_SOURCES += \
        lib/netlink-socket.h \
        lib/ovs-numa.c \
        lib/ovs-numa.h \
-       lib/rtnetlink-link.c \
-       lib/rtnetlink-link.h \
+       lib/rtnetlink.c \
+       lib/rtnetlink.h \
        lib/route-table.c \
        lib/route-table.h
 endif
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 0656f36..9213d8b 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -66,7 +66,7 @@
 #include "ovs-atomic.h"
 #include "packets.h"
 #include "poll-loop.h"
-#include "rtnetlink-link.h"
+#include "rtnetlink.h"
 #include "shash.h"
 #include "socket-util.h"
 #include "sset.h"
@@ -541,7 +541,7 @@ netdev_rxq_linux_cast(const struct netdev_rxq *rx)
 }
 
 static void netdev_linux_update(struct netdev_linux *netdev,
-                                const struct rtnetlink_link_change *)
+                                const struct rtnetlink_change *)
     OVS_REQUIRES(netdev->mutex);
 static void netdev_linux_changed(struct netdev_linux *netdev,
                                  unsigned int ifi_flags, unsigned int mask)
@@ -601,9 +601,9 @@ netdev_linux_run(void)
         ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub);
         error = nl_sock_recv(sock, &buf, false);
         if (!error) {
-            struct rtnetlink_link_change change;
+            struct rtnetlink_change change;
 
-            if (rtnetlink_link_parse(&buf, &change)) {
+            if (rtnetlink_parse(&buf, &change)) {
                 struct netdev *netdev_ = netdev_from_name(change.ifname);
                 if (netdev_ && is_netdev_linux_class(netdev_->netdev_class)) {
                     struct netdev_linux *netdev = netdev_linux_cast(netdev_);
@@ -674,7 +674,7 @@ netdev_linux_changed(struct netdev_linux *dev,
 
 static void
 netdev_linux_update(struct netdev_linux *dev,
-                    const struct rtnetlink_link_change *change)
+                    const struct rtnetlink_change *change)
     OVS_REQUIRES(dev->mutex)
 {
     if (change->nlmsg_type == RTM_NEWLINK) {
@@ -694,10 +694,9 @@ netdev_linux_update(struct netdev_linux *dev,
             dev->ether_addr_error = 0;
         }
 
-        dev->ifindex = change->ifi_index;
+        dev->ifindex = change->if_index;
         dev->cache_valid |= VALID_IFINDEX;
         dev->get_ifindex_error = 0;
-
     } else {
         netdev_linux_changed(dev, change->ifi_flags, 0);
     }
diff --git a/lib/route-table.c b/lib/route-table.c
index a5a42ca..7d1837c 100644
--- a/lib/route-table.c
+++ b/lib/route-table.c
@@ -30,7 +30,7 @@
 #include "netlink-socket.h"
 #include "ofpbuf.h"
 #include "ovs-router.h"
-#include "rtnetlink-link.h"
+#include "rtnetlink.h"
 #include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(route_table);
@@ -74,7 +74,7 @@ static void route_table_change(const struct route_table_msg 
*, void *);
 static void route_map_clear(void);
 
 static void name_table_init(void);
-static void name_table_change(const struct rtnetlink_link_change *, void *);
+static void name_table_change(const struct rtnetlink_change *, void *);
 
 uint64_t
 route_table_get_change_seq(void)
@@ -113,7 +113,7 @@ route_table_run(void)
 {
     ovs_mutex_lock(&route_table_mutex);
     if (nln) {
-        rtnetlink_link_run();
+        rtnetlink_run();
         nln_run(nln);
 
         if (!route_table_valid) {
@@ -130,7 +130,7 @@ route_table_wait(void)
 {
     ovs_mutex_lock(&route_table_mutex);
     if (nln) {
-        rtnetlink_link_wait();
+        rtnetlink_wait();
         nln_wait(nln);
     }
     ovs_mutex_unlock(&route_table_mutex);
@@ -278,12 +278,12 @@ route_table_fallback_lookup(ovs_be32 ip_dst OVS_UNUSED,
 static void
 name_table_init(void)
 {
-    name_notifier = rtnetlink_link_notifier_create(name_table_change, NULL);
+    name_notifier = rtnetlink_notifier_create(name_table_change, NULL);
 }
 
 
 static void
-name_table_change(const struct rtnetlink_link_change *change OVS_UNUSED,
+name_table_change(const struct rtnetlink_change *change OVS_UNUSED,
                   void *aux OVS_UNUSED)
 {
     /* Changes to interface status can cause routing table changes that some
diff --git a/lib/rtnetlink-link.c b/lib/rtnetlink-link.c
deleted file mode 100644
index 308338f..0000000
--- a/lib/rtnetlink-link.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, 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.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <config.h>
-
-#include "rtnetlink-link.h"
-
-#include <sys/socket.h>
-#include <linux/rtnetlink.h>
-#include <net/if.h>
-
-#include "netlink.h"
-#include "netlink-notifier.h"
-#include "ofpbuf.h"
-
-static struct nln *nln = NULL;
-static struct rtnetlink_link_change rtn_change;
-
-/* Parses a rtnetlink message 'buf' into 'change'.  If 'buf' is unparseable,
- * leaves 'change' untouched and returns false.  Otherwise, populates 'change'
- * and returns true. */
-bool
-rtnetlink_link_parse(struct ofpbuf *buf,
-                     struct rtnetlink_link_change *change)
-{
-    bool parsed;
-
-    /* Policy for RTNLGRP_LINK messages.
-     *
-     * There are *many* more fields in these messages, but currently we
-     * only care about these fields. */
-    static const struct nl_policy policy[] = {
-        [IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
-        [IFLA_MASTER] = { .type = NL_A_U32,    .optional = true },
-        [IFLA_MTU]    = { .type = NL_A_U32,    .optional = true },
-        [IFLA_ADDRESS] = { .type = NL_A_UNSPEC, .optional = true },
-    };
-
-    struct nlattr *attrs[ARRAY_SIZE(policy)];
-
-    parsed = nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg),
-                             policy, attrs, ARRAY_SIZE(policy));
-
-    if (parsed) {
-        const struct nlmsghdr *nlmsg;
-        const struct ifinfomsg *ifinfo;
-
-        nlmsg  = buf->data;
-        ifinfo = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *ifinfo);
-
-        change->nlmsg_type     = nlmsg->nlmsg_type;
-        change->ifi_index      = ifinfo->ifi_index;
-        change->ifname         = nl_attr_get_string(attrs[IFLA_IFNAME]);
-        change->ifi_flags      = ifinfo->ifi_flags;
-        change->master_ifindex = (attrs[IFLA_MASTER]
-                                  ? nl_attr_get_u32(attrs[IFLA_MASTER])
-                                  : 0);
-        change->mtu            = (attrs[IFLA_MTU]
-                                  ? nl_attr_get_u32(attrs[IFLA_MTU])
-                                  : 0);
-
-        if (attrs[IFLA_ADDRESS] &&
-            nl_attr_get_size(attrs[IFLA_ADDRESS]) == ETH_ALEN) {
-            memcpy(change->addr, nl_attr_get(attrs[IFLA_ADDRESS]), ETH_ALEN);
-        } else {
-            memset(change->addr, 0, ETH_ALEN);
-        }
-    }
-
-    return parsed;
-}
-
-static bool
-rtnetlink_link_parse_cb(struct ofpbuf *buf, void *change)
-{
-    return rtnetlink_link_parse(buf, change);
-}
-
-/* Registers 'cb' to be called with auxiliary data 'aux' with network device
- * change notifications.  The notifier is stored in 'notifier', which the
- * caller must not modify or free.
- *
- * This is probably not the function that you want.  You should probably be
- * using dpif_port_poll() or netdev_change_seq(), which unlike this function
- * are not Linux-specific.
- *
- * Returns an initialized nln_notifier if successful, NULL otherwise. */
-struct nln_notifier *
-rtnetlink_link_notifier_create(rtnetlink_link_notify_func *cb, void *aux)
-{
-    if (!nln) {
-        nln = nln_create(NETLINK_ROUTE, RTNLGRP_LINK, rtnetlink_link_parse_cb,
-                         &rtn_change);
-    }
-
-    return nln_notifier_create(nln, (nln_notify_func *) cb, aux);
-}
-
-/* Destroys 'notifier', which must have previously been created with
- * rtnetlink_link_notifier_register(). */
-void
-rtnetlink_link_notifier_destroy(struct nln_notifier *notifier)
-{
-    nln_notifier_destroy(notifier);
-}
-
-/* Calls all of the registered notifiers, passing along any as-yet-unreported
- * netdev change events. */
-void
-rtnetlink_link_run(void)
-{
-    if (nln) {
-        nln_run(nln);
-    }
-}
-
-/* Causes poll_block() to wake up when network device change notifications are
- * ready. */
-void
-rtnetlink_link_wait(void)
-{
-    if (nln) {
-        nln_wait(nln);
-    }
-}
diff --git a/lib/rtnetlink.c b/lib/rtnetlink.c
new file mode 100644
index 0000000..1ecd23b
--- /dev/null
+++ b/lib/rtnetlink.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2009, 2010, 2013, 2015 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "rtnetlink.h"
+
+#include <sys/socket.h>
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+
+#include "netlink.h"
+#include "netlink-notifier.h"
+#include "ofpbuf.h"
+
+static struct nln *nln = NULL;
+static struct rtnetlink_change rtn_change;
+
+/* Returns true if the given netlink msg type corresponds to RTNLGRP_LINK. */
+bool
+rtnetlink_type_is_rtnlgrp_link(uint16_t type)
+{
+    return type == RTM_NEWLINK || type == RTM_DELLINK;
+}
+
+/* Returns true if the given netlink msg type corresponds to
+ * RTNLGRP_IPV4_IFADDR or RTNLGRP_IPV6_IFADDR. */
+bool
+rtnetlink_type_is_rtnlgrp_addr(uint16_t type)
+{
+    return type == RTM_NEWADDR || type == RTM_DELADDR;
+}
+
+/* Parses a rtnetlink message 'buf' into 'change'.  If 'buf' is unparseable,
+ * leaves 'change' untouched and returns false.  Otherwise, populates 'change'
+ * and returns true. */
+bool
+rtnetlink_parse(struct ofpbuf *buf, struct rtnetlink_change *change)
+{
+    const struct nlmsghdr *nlmsg = buf->data;
+    bool parsed = false;
+
+    if (rtnetlink_type_is_rtnlgrp_link(nlmsg->nlmsg_type)) {
+        /* Policy for RTNLGRP_LINK messages.
+         *
+         * There are *many* more fields in these messages, but currently we
+         * only care about these fields. */
+        static const struct nl_policy policy[] = {
+            [IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
+            [IFLA_MASTER] = { .type = NL_A_U32,    .optional = true },
+            [IFLA_MTU]    = { .type = NL_A_U32,    .optional = true },
+            [IFLA_ADDRESS] = { .type = NL_A_UNSPEC, .optional = true },
+        };
+
+        struct nlattr *attrs[ARRAY_SIZE(policy)];
+
+        parsed = nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg),
+                                 policy, attrs, ARRAY_SIZE(policy));
+
+        if (parsed) {
+            const struct ifinfomsg *ifinfo;
+
+            ifinfo = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *ifinfo);
+
+            change->nlmsg_type     = nlmsg->nlmsg_type;
+            change->if_index       = ifinfo->ifi_index;
+            change->ifname         = nl_attr_get_string(attrs[IFLA_IFNAME]);
+            change->ifi_flags      = ifinfo->ifi_flags;
+            change->master_ifindex = (attrs[IFLA_MASTER]
+                                      ? nl_attr_get_u32(attrs[IFLA_MASTER])
+                                      : 0);
+            change->mtu            = (attrs[IFLA_MTU]
+                                      ? nl_attr_get_u32(attrs[IFLA_MTU])
+                                      : 0);
+
+            if (attrs[IFLA_ADDRESS] &&
+                nl_attr_get_size(attrs[IFLA_ADDRESS]) == ETH_ALEN) {
+                memcpy(change->addr, nl_attr_get(attrs[IFLA_ADDRESS]),
+                       ETH_ALEN);
+            } else {
+                memset(change->addr, 0, ETH_ALEN);
+            }
+        }
+    } else if (rtnetlink_type_is_rtnlgrp_addr(nlmsg->nlmsg_type)) {
+        /* Policy for RTNLGRP_IPV4_IFADDR/RTNLGRP_IPV6_IFADDR messages.
+         *
+         * There are *many* more fields in these messages, but currently we
+         * only care about these fields. */
+        static const struct nl_policy policy[] = {
+            [IFA_LABEL] = { .type = NL_A_STRING, .optional = false },
+        };
+
+        struct nlattr *attrs[ARRAY_SIZE(policy)];
+
+        parsed = nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct ifaddrmsg),
+                                 policy, attrs, ARRAY_SIZE(policy));
+
+        if (parsed) {
+            const struct ifaddrmsg *ifaddr;
+
+            ifaddr = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *ifaddr);
+
+            change->nlmsg_type     = nlmsg->nlmsg_type;
+            change->if_index       = ifaddr->ifa_index;
+            change->ifname         = nl_attr_get_string(attrs[IFA_LABEL]);
+        }
+    }
+
+    return parsed;
+}
+
+static bool
+rtnetlink_parse_cb(struct ofpbuf *buf, void *change)
+{
+    return rtnetlink_parse(buf, change);
+}
+
+/* Registers 'cb' to be called with auxiliary data 'aux' with network device
+ * change notifications.  The notifier is stored in 'notifier', which the
+ * caller must not modify or free.
+ *
+ * This is probably not the function that you want.  You should probably be
+ * using dpif_port_poll() or netdev_change_seq(), which unlike this function
+ * are not Linux-specific.
+ *
+ * xxx Joins more multicast groups when needed.
+ *
+ * Returns an initialized nln_notifier if successful, NULL otherwise. */
+struct nln_notifier *
+rtnetlink_notifier_create(rtnetlink_notify_func *cb, void *aux)
+{
+    if (!nln) {
+        nln = nln_create(NETLINK_ROUTE, RTNLGRP_LINK, rtnetlink_parse_cb,
+                         &rtn_change);
+    }
+
+    return nln_notifier_create(nln, (nln_notify_func *) cb, aux);
+}
+
+/* Destroys 'notifier', which must have previously been created with
+ * rtnetlink_notifier_register(). */
+void
+rtnetlink_notifier_destroy(struct nln_notifier *notifier)
+{
+    nln_notifier_destroy(notifier);
+}
+
+/* Calls all of the registered notifiers, passing along any as-yet-unreported
+ * netdev change events. */
+void
+rtnetlink_run(void)
+{
+    if (nln) {
+        nln_run(nln);
+    }
+}
+
+/* Causes poll_block() to wake up when network device change notifications are
+ * ready. */
+void
+rtnetlink_wait(void)
+{
+    if (nln) {
+        nln_wait(nln);
+    }
+}
diff --git a/lib/rtnetlink-link.h b/lib/rtnetlink.h
similarity index 64%
rename from lib/rtnetlink-link.h
rename to lib/rtnetlink.h
index d0d9a75..f2da394 100644
--- a/lib/rtnetlink-link.h
+++ b/lib/rtnetlink.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira, Inc.
+ * Copyright (c) 2009, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,36 +28,41 @@ struct nln_notifier;
  * Linux-specific code. */
 
 /* A digested version of an rtnetlink_link message sent down by the kernel to
- * indicate that a network device has been created, destroyed or changed.  */
-struct rtnetlink_link_change {
+ * indicate that a network device's status (link or address) has been changed.
+ */
+struct rtnetlink_change {
     /* Copied from struct nlmsghdr. */
     int nlmsg_type;             /* e.g. RTM_NEWLINK, RTM_DELLINK. */
 
-    /* Copied from struct ifinfomsg. */
-    int ifi_index;              /* Index of network device. */
-
-    /* Extracted from Netlink attributes. */
+    /* Common attributes. */
+    int if_index;               /* Index of network device. */
     const char *ifname;         /* Name of network device. */
+
+    /* Network device link status. */
     int master_ifindex;         /* Ifindex of datapath master (0 if none). */
     int mtu;                    /* Current MTU. */
     uint8_t addr[ETH_ALEN];
     unsigned int ifi_flags;     /* Flags of network device. */
+
+    /* Network device address status. */
+    /* xxx To be added when needed. */
 };
 
 /* Function called to report that a netdev has changed.  'change' describes the
  * specific change.  It may be null if the buffer of change information
  * overflowed, in which case the function must assume that every device may
  * have changed.  'aux' is as specified in the call to
- * rtnetlink_link_notifier_register().  */
+ * rtnetlink_notifier_register().  */
 typedef
-void rtnetlink_link_notify_func(const struct rtnetlink_link_change *change,
-                                void *aux);
+void rtnetlink_notify_func(const struct rtnetlink_change *change,
+                           void *aux);
 
-bool rtnetlink_link_parse(struct ofpbuf *buf,
-                          struct rtnetlink_link_change *change);
+bool rtnetlink_type_is_rtnlgrp_link(uint16_t type);
+bool rtnetlink_type_is_rtnlgrp_addr(uint16_t type);
+bool rtnetlink_parse(struct ofpbuf *buf, struct rtnetlink_change *change);
 struct nln_notifier *
-rtnetlink_link_notifier_create(rtnetlink_link_notify_func *, void *aux);
-void rtnetlink_link_notifier_destroy(struct nln_notifier *);
-void rtnetlink_link_run(void);
-void rtnetlink_link_wait(void);
-#endif /* rtnetlink-link.h */
+rtnetlink_notifier_create(rtnetlink_notify_func *, void *aux);
+void rtnetlink_notifier_destroy(struct nln_notifier *);
+void rtnetlink_run(void);
+void rtnetlink_wait(void);
+#endif /* rtnetlink.h */
diff --git a/lib/vlandev.c b/lib/vlandev.c
index 99c99de..d2a3191 100644
--- a/lib/vlandev.c
+++ b/lib/vlandev.c
@@ -162,7 +162,7 @@ vlandev_get_name(const char *real_dev_name, int vid)
 /* The Linux vlandev implementation. */
 
 #ifdef __linux__
-#include "rtnetlink-link.h"
+#include "rtnetlink.h"
 #include <linux/if_vlan.h>
 #include <linux/sockios.h>
 #include "netdev-linux.h"
@@ -171,7 +171,7 @@ static struct nln_notifier *vlan_cache_notifier;
 static bool cache_valid;
 
 static void
-vlan_cache_cb(const struct rtnetlink_link_change *change OVS_UNUSED,
+vlan_cache_cb(const struct rtnetlink_change *change OVS_UNUSED,
               void *aux OVS_UNUSED)
 {
     cache_valid = false;
@@ -185,8 +185,8 @@ vlandev_linux_refresh(void)
     FILE *stream;
 
     if (!vlan_cache_notifier) {
-        vlan_cache_notifier = rtnetlink_link_notifier_create(vlan_cache_cb,
-                                                             NULL);
+        vlan_cache_notifier = rtnetlink_notifier_create(vlan_cache_cb,
+                                                        NULL);
         if (!vlan_cache_notifier) {
             return EINVAL;
         }
-- 
1.7.9.5

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to