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 <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev