Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hotswapping to FromHost and ToHost elements #424

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 57 additions & 10 deletions elements/userlevel/fromhost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ FromHost::try_linux_universal(ErrorHandler *errh)
{
int fd;
#ifdef HAVE_PROPER
int e;
fd = prop_open("/dev/net/tun", O_RDWR);
if (fd >= 0) {
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
int e = errno;
e = errno;
errh->error("fcntl /dev/net/tun: %s", strerror(e));
close(fd);
return -e;
Expand Down Expand Up @@ -141,7 +142,6 @@ FromHost::setup_tun(ErrorHandler *errh)
sa << "/sbin/ifconfig " << _dev_name << " hw ether " << _macaddr.unparse_colon();
if (system(sa.c_str()) != 0)
errh->error("%s: %s", sa.c_str(), strerror(errno));

sa.clear();
sa << "/sbin/ifconfig " << _dev_name << " arp";
if (system(sa.c_str()) != 0)
Expand Down Expand Up @@ -193,19 +193,68 @@ FromHost::dealloc_tun()
}
}

FromHost *
FromHost::hotswap_element() const
{
if (Element *e = Element::hotswap_element())
if (FromHost *fh = static_cast<FromHost *>(e->cast("FromHost")))
if (fh->_dev_name == _dev_name)
return fh;
return 0;
}

void
FromHost::take_state(Element *e, ErrorHandler *errh)
{
(void)errh;
FromHost *o = static_cast<FromHost *>(e); // checked by hotswap_element()

_fd = o->fd();
_dev_name = o->dev_name();

_mtu_in = o->_mtu_in;
_mtu_out = o->_mtu_out;

_macaddr = o->_macaddr;

_near = o->_near;
_mask = o->_mask;
_gw = o->_gw;

#if HAVE_IP6
_near6 = o->_near6;
_prefix6 = o->_prefix6;
#endif

_headroom = o->_headroom;

o->remove_select(_fd, SELECT_READ);
o->_fd = -1;
}

int
FromHost::initialize(ErrorHandler *errh)
{
if (try_linux_universal(errh) < 0)
return -1;
if (setup_tun(errh) < 0)
return -1;
int ret = -1;

ScheduleInfo::join_scheduler(this, &_task, errh);
_nonfull_signal = Notifier::downstream_full_signal(this, 0, &_task);

if (hotswap_element()) {
goto out;
}

if (try_linux_universal(errh) < 0)
goto err;
if (setup_tun(errh) < 0)
goto err;

add_select(_fd, SELECT_READ);
return 0;

out:
ret = 0;
err:
return ret;
}

void
Expand Down Expand Up @@ -242,15 +291,14 @@ FromHost::selected(int fd, int)
output(0).push(p);
} else {
p->kill();
printf("FromHost read(print)\n");
perror("FromHost read");
}

if (!_nonfull_signal) {
remove_select(_fd, SELECT_READ);
return;
}


}

bool
Expand All @@ -261,7 +309,6 @@ FromHost::run_task(Task *)

add_select(_fd, SELECT_READ);
return true;

}

String
Expand Down
8 changes: 4 additions & 4 deletions elements/userlevel/fromhost.hh
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,8 @@ CLICK_DECLS
*
*/

class FromHost : public Element { public:


class FromHost : public Element {
public:
enum ConfigurePhase {
CONFIGURE_PHASE_FROMHOST = CONFIGURE_PHASE_DEFAULT,
CONFIGURE_PHASE_TOHOST = CONFIGURE_PHASE_FROMHOST + 1
Expand All @@ -112,6 +111,8 @@ class FromHost : public Element { public:
int initialize(ErrorHandler *) CLICK_COLD;
void cleanup(CleanupStage) CLICK_COLD;
void add_handlers() CLICK_COLD;
FromHost *hotswap_element() const;
void take_state(Element *, ErrorHandler *);

int fd() const { return _fd; }
String dev_name() const { return _dev_name; }
Expand Down Expand Up @@ -149,7 +150,6 @@ class FromHost : public Element { public:
void dealloc_tun();

static String read_param(Element *, void *) CLICK_COLD;

};

CLICK_ENDDECLS
Expand Down
50 changes: 39 additions & 11 deletions elements/userlevel/tohost.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@

CLICK_DECLS

ToHost::ToHost()
: _fd(-1), _drops(0)
ToHost::ToHost(): _fd(-1), _drops(0)
{
}

Expand All @@ -55,16 +54,17 @@ ToHost::configure(Vector<String> &conf, ErrorHandler *errh)
.complete();
}

int
ToHost::initialize(ErrorHandler *errh)
int ToHost::find_fromhost(ErrorHandler *errh)
{
int ei;
FromHost *s;
Element *e;

//find a FromHost and reuse its socket
for (int ei = 0; ei < router()->nelements() && _fd < 0; ei++) {
Element *e = router()->element(ei);
FromHost *s = (FromHost *)e->cast("FromHost");
if (s &&
s->dev_name() == _dev_name &&
s->fd() > 0) {
for (ei = 0; ei < router()->nelements() && _fd < 0; ei++) {
e = router()->element(ei);
s = (FromHost *)e->cast("FromHost");
if (s && s->dev_name() == _dev_name && s->fd() > 0) {
_fd = s->fd();
return 0;
}
Expand All @@ -74,6 +74,33 @@ ToHost::initialize(ErrorHandler *errh)
_dev_name.c_str());
}

int
ToHost::initialize(ErrorHandler *errh)
{
if (hotswap_element()) {
return 0;
}

return find_fromhost(errh);
}

ToHost *
ToHost::hotswap_element() const
{
if (Element *e = Element::hotswap_element())
if (ToHost *th = static_cast<ToHost *>(e->cast("ToHost")))
if (th->_dev_name == _dev_name)
return th;
return 0;
}

void
ToHost::take_state(Element *e, ErrorHandler *errh)
{
(void)e;
find_fromhost(errh);
}

void
ToHost::push(int, Packet *p)
{
Expand All @@ -97,9 +124,10 @@ ToHost::push(int, Packet *p)
click_chatter("ToHost(%s): write failed: %s", _dev_name.c_str(), strerror(errno));
}
q->kill();
} else
} else {
click_chatter("%p{element}: out of memory", this);
}
}

void
ToHost::add_handlers()
Expand Down
9 changes: 6 additions & 3 deletions elements/userlevel/tohost.hh
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ CLICK_DECLS
*
*/

class ToHost : public Element { public:

class ToHost : public Element {
public:
ToHost() CLICK_COLD;
~ToHost() CLICK_COLD;

Expand All @@ -57,15 +57,18 @@ class ToHost : public Element { public:
int configure(Vector<String> &, ErrorHandler *) CLICK_COLD;
int initialize(ErrorHandler *) CLICK_COLD;
void add_handlers() CLICK_COLD;
ToHost *hotswap_element() const;
void take_state(Element *, ErrorHandler *);

void push(int port, Packet *);

private:

int _fd;
int _drops;
String _dev_name;

int find_fromhost(ErrorHandler *);

};

CLICK_ENDDECLS
Expand Down