ethertap.cc (12632:a00c27d2256b) | ethertap.cc (12978:3acf5f78d541) |
---|---|
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 392 unchanged lines hidden (view full) --- 401 return write(socket, data, len) == len; 402} 403 404 405#if USE_TUNTAP 406 407EtherTap::EtherTap(const Params *p) : EtherTapBase(p) 408{ | 1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 392 unchanged lines hidden (view full) --- 401 return write(socket, data, len) == len; 402} 403 404 405#if USE_TUNTAP 406 407EtherTap::EtherTap(const Params *p) : EtherTapBase(p) 408{ |
409 int fd = open(p->tun_clone_device.c_str(), O_RDWR); | 409 int fd = open(p->tun_clone_device.c_str(), O_RDWR | O_NONBLOCK); |
410 if (fd < 0) 411 panic("Couldn't open %s.\n", p->tun_clone_device); 412 413 struct ifreq ifr; 414 memset(&ifr, 0, sizeof(ifr)); 415 ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 416 strncpy(ifr.ifr_name, p->tap_device_name.c_str(), IFNAMSIZ - 1); 417 --- 15 unchanged lines hidden (view full) --- 433EtherTap::recvReal(int revent) 434{ 435 if (revent & POLLERR) 436 panic("Error polling for tap data.\n"); 437 438 if (!(revent & POLLIN)) 439 return; 440 | 410 if (fd < 0) 411 panic("Couldn't open %s.\n", p->tun_clone_device); 412 413 struct ifreq ifr; 414 memset(&ifr, 0, sizeof(ifr)); 415 ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 416 strncpy(ifr.ifr_name, p->tap_device_name.c_str(), IFNAMSIZ - 1); 417 --- 15 unchanged lines hidden (view full) --- 433EtherTap::recvReal(int revent) 434{ 435 if (revent & POLLERR) 436 panic("Error polling for tap data.\n"); 437 438 if (!(revent & POLLIN)) 439 return; 440 |
441 ssize_t ret = read(tap, buffer, buflen); 442 if (ret < 0) 443 panic("Failed to read from tap device.\n"); | 441 ssize_t ret; 442 while ((ret = read(tap, buffer, buflen))) { 443 if (ret < 0) { 444 if (errno == EAGAIN) 445 break; 446 panic("Failed to read from tap device.\n"); 447 } |
444 | 448 |
445 sendSimulated(buffer, ret); | 449 sendSimulated(buffer, ret); 450 } |
446} 447 448bool 449EtherTap::sendReal(const void *data, size_t len) 450{ | 451} 452 453bool 454EtherTap::sendReal(const void *data, size_t len) 455{ |
451 if (write(tap, data, len) != len) 452 panic("Failed to write data to tap device.\n"); | 456 int n; 457 pollfd pfd[1]; 458 pfd->fd = tap; 459 pfd->events = POLLOUT; 460 461 // `tap` is a nonblock fd. Here we try to write until success, and use 462 // poll to make a blocking wait. 463 while ((n = write(tap, data, len)) != len) { 464 if (errno != EAGAIN) 465 panic("Failed to write data to tap device.\n"); 466 pfd->revents = 0; 467 int ret = poll(pfd, 1, -1); 468 // timeout is set to inf, we shouldn't get 0 in any case. 469 assert(ret != 0); 470 if (ret == -1 || (ret == 1 && (pfd->revents & POLLERR))) { 471 panic("Failed when polling to write data to tap device.\n"); 472 } 473 } |
453 return true; 454} 455 456EtherTap * 457EtherTapParams::create() 458{ 459 return new EtherTap(this); 460} 461 462#endif 463 464EtherTapStub * 465EtherTapStubParams::create() 466{ 467 return new EtherTapStub(this); 468} | 474 return true; 475} 476 477EtherTap * 478EtherTapParams::create() 479{ 480 return new EtherTap(this); 481} 482 483#endif 484 485EtherTapStub * 486EtherTapStubParams::create() 487{ 488 return new EtherTapStub(this); 489} |