From 8d685fc11f7b743aa68b91a51e58ef8d4bb501f4 Mon Sep 17 00:00:00 2001 From: Shlomo Shenzis Date: Sun, 2 Dec 2018 13:59:32 -0800 Subject: [PATCH] Added hotwapping support to FromHost and ToHost elements Signed-off-by: Shlomo Shenzis --- elements/userlevel/fromhost.cc | 67 +++++++++++++++++++++++++++++----- elements/userlevel/fromhost.hh | 8 ++-- elements/userlevel/tohost.cc | 50 +++++++++++++++++++------ elements/userlevel/tohost.hh | 9 +++-- 4 files changed, 106 insertions(+), 28 deletions(-) diff --git a/elements/userlevel/fromhost.cc b/elements/userlevel/fromhost.cc index 50e5531155..4bd90f49b3 100644 --- a/elements/userlevel/fromhost.cc +++ b/elements/userlevel/fromhost.cc @@ -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; @@ -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) @@ -193,19 +193,68 @@ FromHost::dealloc_tun() } } +FromHost * +FromHost::hotswap_element() const +{ + if (Element *e = Element::hotswap_element()) + if (FromHost *fh = static_cast(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(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 @@ -242,6 +291,7 @@ FromHost::selected(int fd, int) output(0).push(p); } else { p->kill(); + printf("FromHost read(print)\n"); perror("FromHost read"); } @@ -249,8 +299,6 @@ FromHost::selected(int fd, int) remove_select(_fd, SELECT_READ); return; } - - } bool @@ -261,7 +309,6 @@ FromHost::run_task(Task *) add_select(_fd, SELECT_READ); return true; - } String diff --git a/elements/userlevel/fromhost.hh b/elements/userlevel/fromhost.hh index 2427d30320..45e74c1e00 100644 --- a/elements/userlevel/fromhost.hh +++ b/elements/userlevel/fromhost.hh @@ -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 @@ -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; } @@ -149,7 +150,6 @@ class FromHost : public Element { public: void dealloc_tun(); static String read_param(Element *, void *) CLICK_COLD; - }; CLICK_ENDDECLS diff --git a/elements/userlevel/tohost.cc b/elements/userlevel/tohost.cc index c4686c74b3..9ce6bd6e4c 100644 --- a/elements/userlevel/tohost.cc +++ b/elements/userlevel/tohost.cc @@ -38,8 +38,7 @@ CLICK_DECLS -ToHost::ToHost() - : _fd(-1), _drops(0) +ToHost::ToHost(): _fd(-1), _drops(0) { } @@ -55,16 +54,17 @@ ToHost::configure(Vector &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; } @@ -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(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) { @@ -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() diff --git a/elements/userlevel/tohost.hh b/elements/userlevel/tohost.hh index a3abf1a6de..43eb3ad75e 100644 --- a/elements/userlevel/tohost.hh +++ b/elements/userlevel/tohost.hh @@ -44,8 +44,8 @@ CLICK_DECLS * */ -class ToHost : public Element { public: - +class ToHost : public Element { +public: ToHost() CLICK_COLD; ~ToHost() CLICK_COLD; @@ -57,15 +57,18 @@ class ToHost : public Element { public: int configure(Vector &, 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