static int
netdev_linux_open(struct netdev_dev *netdev_dev_, struct netdev **netdevp)
{
- struct netdev_dev_linux *netdev_dev = netdev_dev_linux_cast(netdev_dev_);
struct netdev_linux *netdev;
enum netdev_flags flags;
int error;
}
}
- if (!strcmp(netdev_dev_get_type(netdev_dev_), "tap") &&
- !netdev_dev->state.tap.opened) {
-
- /* We assume that the first user of the tap device is the primary user
- * and give them the tap FD. Subsequent users probably just expect
- * this to be a system device so open it normally to avoid send/receive
- * directions appearing to be reversed. */
- netdev->fd = netdev_dev->state.tap.fd;
- netdev_dev->state.tap.opened = true;
- }
-
*netdevp = &netdev->netdev;
return 0;
netdev_linux_listen(struct netdev *netdev_)
{
struct netdev_linux *netdev = netdev_linux_cast(netdev_);
+ struct netdev_dev_linux *netdev_dev =
+ netdev_dev_linux_cast(netdev_get_dev(netdev_));
struct sockaddr_ll sll;
int ifindex;
int error;
return 0;
}
+ if (!strcmp(netdev_get_type(netdev_), "tap")
+ && !netdev_dev->state.tap.opened) {
+ netdev->fd = netdev_dev->state.tap.fd;
+ netdev_dev->state.tap.opened = true;
+ return 0;
+ }
+
/* Create file descriptor. */
fd = socket(PF_PACKET, SOCK_RAW, 0);
if (fd < 0) {
struct netdev_dev_linux *netdev_dev =
netdev_dev_linux_cast(netdev_get_dev(netdev_));
int error;
+ bool up_again = false;
if (netdev_dev->cache_valid & VALID_ETHERADDR) {
if (netdev_dev->ether_addr_error) {
netdev_dev->cache_valid &= ~VALID_ETHERADDR;
}
+ /* Tap devices must be brought down before setting the address. */
+ if (!strcmp(netdev_get_type(netdev_), "tap")) {
+ enum netdev_flags flags;
+
+ if (!netdev_get_flags(netdev_, &flags) && (flags & NETDEV_UP)) {
+ netdev_turn_flags_off(netdev_, NETDEV_UP, false);
+ up_again = true;
+ }
+ }
error = set_etheraddr(netdev_get_name(netdev_), mac);
if (!error || error == ENODEV) {
netdev_dev->ether_addr_error = error;
}
}
+ if (up_again) {
+ netdev_turn_flags_on(netdev_, NETDEV_UP, false);
+ }
+
return error;
}
int error;
error = netdev_vport_get_stats(netdev_, stats);
- if (error) {
+ if (error && error != ENOENT) {
VLOG_WARN_RL(&rl, "%s: obtaining netdev stats via vport failed "
"(%s)", netdev_get_name(netdev_), strerror(error));
}