struct netdev_dev_bsd {
struct netdev_dev netdev_dev;
unsigned int cache_valid;
+ unsigned int change_seq;
int ifindex;
uint8_t etheraddr[ETH_ADDR_LEN];
rtbsd_notifier_wait();
}
+static void
+netdev_dev_bsd_changed(struct netdev_dev_bsd *dev)
+{
+ dev->change_seq++;
+ if (!dev->change_seq) {
+ dev->change_seq++;
+ }
+}
+
/* Invalidate cache in case of interface status change. */
static void
netdev_bsd_cache_cb(const struct rtbsd_change *change,
if (is_netdev_bsd_class(netdev_class)) {
dev = netdev_dev_bsd_cast(base_dev);
dev->cache_valid = 0;
+ netdev_dev_bsd_changed(dev);
}
}
} else {
SHASH_FOR_EACH (node, &device_shash) {
dev = node->data;
dev->cache_valid = 0;
+ netdev_dev_bsd_changed(dev);
}
shash_destroy(&device_shash);
}
int error;
error = cache_notifier_ref();
- if (!error) {
+ if (error) {
return error;
}
netdev_dev = xzalloc(sizeof *netdev_dev);
+ netdev_dev->change_seq = 1;
netdev_dev_init(&netdev_dev->netdev_dev, name, class);
*netdev_devp = &netdev_dev->netdev_dev;
struct ifreq ifr;
error = cache_notifier_ref();
- if (!error) {
+ if (error) {
goto error;
}
/* Create a tap device by opening /dev/tap. The TAPGIFNAME ioctl is used
* to retrieve the name of the tap device. */
netdev_dev->tap_fd = open("/dev/tap", O_RDWR);
+ netdev_dev->change_seq = 1;
if (netdev_dev->tap_fd < 0) {
error = errno;
VLOG_WARN("opening \"/dev/tap\" failed: %s", strerror(error));
goto error;
}
+ netdev_dev_bsd_changed(netdev_dev_bsd_cast(netdev_get_dev(netdev_)));
+
/* initialize netdev->netdev_fd */
fd = pcap_get_selectable_fd(netdev->pcap_handle);
if (fd == -1) {
if (!error) {
netdev_dev->cache_valid |= VALID_ETHERADDR;
memcpy(netdev_dev->etheraddr, mac, ETH_ADDR_LEN);
+ netdev_dev_bsd_changed(netdev_dev);
}
} else {
error = 0;
error = do_set_addr(netdev_, SIOCSIFNETMASK,
"SIOCSIFNETMASK", mask);
}
+ netdev_dev_bsd_changed(netdev_dev);
}
return error;
}
new_flags = (old_flags & ~nd_to_iff_flags(off)) | nd_to_iff_flags(on);
if (new_flags != old_flags) {
error = set_flags(netdev, new_flags);
+ netdev_dev_bsd_changed(netdev_dev_bsd_cast(netdev_get_dev(netdev)));
}
}
return error;
}
+static unsigned int
+netdev_bsd_change_seq(const struct netdev *netdev)
+{
+ return netdev_dev_bsd_cast(netdev_get_dev(netdev))->change_seq;
+}
+
const struct netdev_class netdev_bsd_class = {
"system",
netdev_bsd_update_flags,
- NULL, /* change_seq */
+ netdev_bsd_change_seq
};
const struct netdev_class netdev_tap_class = {
netdev_bsd_update_flags,
- NULL, /* change_seq */
+ netdev_bsd_change_seq
};
\f